Mach meinen Pseudocode real

8

Ich habe einen Java-Pseudocode, der Leerzeichen anstelle von geschweiften Klammern verwendet, und ich möchte, dass Sie ihn konvertieren.

I / O.

Ihr Programm sollte eine Eingabedatei zusammen mit einer Zahl verwenden, die angibt, wie viele Leerzeichen zum Einrücken eines Blocks verwendet werden. Hier ist ein Beispiel:

$ convert.lang input.p 4
// Konvertiere mit 4 Leerzeichen als Blocktrennzeichen
$ convert.lang input.p 2
// Konvertiere mit 2 Leerzeichen als Blocktrennzeichen

Anschließend sollte das Ergebnis mit dem angegebenen Blocktrennzeichen konvertiert und das Ergebnis in stdout ausgegeben werden.

Das Fleisch des Programms

Blöcke, die mit :und jede Zeile innerhalb des Blocks geöffnet werden, werden mit dem Blocktrennzeichen wie Python-Code eingerückt.

während (wahr):
    System.out.println ("Test");

Jedes :wird durch a ersetzt {und a }wird an das Ende des Blocks angehängt.

while (wahr) {
    System.out.println ("Test");
}}

Beispiele

Eingang:

öffentlicher Klassentest:
    public static void main (String [] args):
        System.out.println ("Java ist ausführlich ...");

Ausgabe:

$ convert Test.pseudojava 4
öffentlicher Klassentest {
    public static void main (String [] args) {
        System.out.println ("Java ist ausführlich ...");
    }}
}}

Eingang:

Main():
  printf ("Hallo Welt");

Ausgabe:

$ convert test.file 2
main () {
  printf ("Hallo Welt");
}}

Eingang:

def generic_op (the_stack, func):
    # Generischer Op-Handling-Code
    b = the_stack.pop ()
    wenn isinstance (b, Liste):
        wenn b:
            Rückkehr
        top = b.pop (0)
        während b:
            top = func (top, b.pop (0))
        the_stack.push (oben)
    sonst:
        a = the_stack.pop ()
        Rückgabefunktion (a, b)

Ausgabe:

$ convert code.py 4
def generic_op (the_stack, func) {
    # Generischer Op-Handling-Code
    b = the_stack.pop ()
    if isinstance (b, Liste) {
        wenn b {
            Rückkehr
        }}
        top = b.pop (0)
        während b {
            top = func (top, b.pop (0))
        }}
        the_stack.push (oben)
    }}
    sonst {
        a = the_stack.pop ()
        Rückgabefunktion (a, b)
    }}
}}

Wertung

Der Code mit der geringsten Anzahl von Bytes gewinnt!

Phase
quelle
1
Können wir davon ausgehen, dass die Eingabe keine Kommentare enthält?
Martin Ender
1
@ MartinBüttner Es kann Kommentare enthalten, aber die Kommentare enthalten kein ':'. Grundsätzlich ja.
Phase
3
Was ist mit Beschriftungen, die der übliche Grund dafür sind, dass eine Zeile in einer gültigen Java-Quelle in einem Doppelpunkt endet?
Peter Taylor
1
Ich habe noch nie ein Etikett gesehen, außer am Anfang einer Zeile.
SuperJedi224
2
Ich wurde gerade daran erinnert, wie sehr ich Java hasse.
Lirtosiast

Antworten:

5

Perl, 41 Bytes

#!perl -p0
1while s/( *).*\K:((
\1 .*)+)/ {\2
\1}/

Wenn man den Shebang als zwei zählt, wird die Eingabe von stdin übernommen. Ein Befehlszeilenargument muss nicht angegeben werden. Jeder gültige Verschachtelungskontext kann ermittelt (und abgeglichen) werden, ohne die Einrückungsgröße zu kennen.


Regex-Zusammenbruch

( *)                   # as many spaces as possible (\1)
    .*                 # as many non-newline characters as possible \
                         (greediness ensures this will always match a full line)
      \K               # keep all that (i.e. look-behind assertion)
        :              # colon at eol (newline must be matched next)
         (
          (
           \n\1        # newline with at least one more space than the first match
                .*     # non-newlines until eol
                  )+   # as many of these lines as possible
                    )  # grouping (\2)

Beispielnutzung

in1.dat

public class Test:
    public static void main(String[] args):
        System.out.println("Java is verbose...");

Ausgabe

$ perl py2java.pl < in1.dat
public class Test {
    public static void main(String[] args) {
        System.out.println("Java is verbose...");
    }
}

in2.dat

main():
  printf("Hello World");

Ausgabe

$ perl py2java.pl < in2.dat
main() {
  printf("Hello World");
}

in3.dat

def generic_op(the_stack, func):
    # Generic op handling code
    b = the_stack.pop()
    if isinstance(b, list):
        if b:
            return
        top = b.pop(0)
        while b:
            top = func(top, b.pop(0))
        the_stack.push(top)
    else:
        a = the_stack.pop()
        return func(a, b)

Ausgabe

$ perl py2java.pl < in3.dat
def generic_op(the_stack, func) {
    # Generic op handling code
    b = the_stack.pop()
    if isinstance(b, list) {
        if b {
            return
        }
        top = b.pop(0)
        while b {
            top = func(top, b.pop(0))
        }
        the_stack.push(top)
    }
    else {
        a = the_stack.pop()
        return func(a, b)
    }
}
primo
quelle
Ich habe das gerade in Rubin geschrieben
Nicht, dass Charles
2

Python 3, 299 265 Bytes

import sys;s=int(sys.argv[2]);t="";b=0
for l in open(sys.argv[1]):
 h=l;g=0
 for c in l:
  if c!=" ":break
  g+=1
 if g/s<b:h=" "*g+"}\n"+h;b-=1
 if l.strip().endswith(":"):h=l.split(":")[0];h+=" {";b+=1
 t+=h+"\n"
b-=1
while b>-1:
 t+=" "*(b*s)+"}\n"b-=1
print(t)

Boom bam pow.

Verwendeter Algorithmus:

// globale vars
string total // total modifiziertes Programm
int b // Puffer einrücken

Zeile durch Zeilen: // über jede Zeile iterieren
  string mline = "" // Zeile, die zur Gesamtsumme hinzugefügt werden soll

  // Berechne die Anzahl der Leerzeichen vor der Zeile (könnte viel einfacher sein)
  int Leerzeichen = 0 // Gesamträume
  c durch Zeile: // gehe jedes Zeichen in der Zeile durch
    if c! = "": // wenn das aktuelle Zeichen kein Leerzeichen ist (was bedeutet, dass wir alle durchgesehen haben
        break // Durchbrechen der Iteration durch Zeichen
    Leerzeichen ++ // Inkrementiere die Leerzeichen, weil wir ein Leerzeichen getroffen haben (hurr derr)

  if Leerzeichen / SPACE_SETTING <b: // wenn die Anzahl der Einrückungen der aktuellen Zeile kleiner als der Einrückungspuffer ist
    mline = "} \ n" + line // schließende Klammer am Zeilenanfang hinzufügen
    b-- // Puffer dekrementieren

  if line.endswith (":"): // wenn die Zeile mit einem `:` endet
    entfernen: aus der Zeile
    mline + = "{" // anhängen {
    b ++ // Puffer erhöhen
  total + = mline // Geänderte Zeile zu total hinzufügen

drucken (gesamt)
Phase
quelle
Können Sie eine Erklärung hinzufügen?
TanMath
@ TanMath Fügte den Algorithmus hinzu, den ich verwendet habe
Phase
Funktioniert es mit Python 2?
wb9688
@ wb9688 Keine Ahnung, ich habe es nur mit Python 3 getestet
Phase
Ich habe gerade getestet, und es funktioniert mit Python 2
wb9688
2

Ruby, 70

x=$_+"
"
1while x.sub! /^(( *).*):
((\2 .*?
)*)/,'\1 {
\3\2}
'
$><<x

Fügt einen nachgestellten Zeilenumbruch hinzu. Benötigt nicht den Parameter für die Blockgröße des Einzugs.

Führen Sie dies mit -n0(das ist wirklich 68 + 2). Vielen Dank an @primo für das Speichern von über einem Dutzend Bytes.

Nicht dass Charles
quelle
Ich denke, -p0funktioniert auch für Ruby ( -0liest alle Eingaben auf einmal, -pspeichert stdin darin $_und druckt es am Ende automatisch aus).
Primo
@primo Guter Punkt. Falls es mit meinem obigen Kommentar nicht klar war, ist dies kein Port Ihres Codes, sondern meine eigene Arbeit, die genau das tut, was Ihre tut (aber mit mehr Bytes)
Nicht, dass Charles
Ich habe es richtig verstanden und nur einen Tipp gegeben, um das (ziemlich ausführliche) zu entfernen x=$<.readlines*''. Während ich das mache, gibt es sub!auch eine Überladung mit zwei Parametern (anstelle eines Parameters + Blocks), die eine Ersatzzeichenfolge akzeptiert, sodass Sie usw. verwenden \1können \2, anstatt alles verketten zu müssen.
Primo
@primo Danke! Ich habe die Zwei-Parameter-Version schon einmal ausprobiert und sie letzte Nacht irgendwann aufgegeben.
Nicht dass Charles