Es gibt viele Formalismen, so dass Sie vielleicht andere nützliche Quellen finden. Ich hoffe, dass ich dies klar genug formulieren kann, damit sie nicht notwendig sind.
Ein RM besteht aus einer endlichen Zustandsmaschine und einer endlichen Anzahl benannter Register, von denen jedes eine nicht negative ganze Zahl enthält. Um die Texteingabe zu vereinfachen, müssen für diese Aufgabe auch die Status benannt werden.
Es gibt drei Arten von Zuständen: Inkrementieren und Dekrementieren, die beide auf ein bestimmtes Register verweisen. und kündigen. Ein Inkrementierungszustand inkrementiert sein Register und übergibt die Steuerung an seinen einen Nachfolger. Ein Dekrementierungszustand hat zwei Nachfolger: Wenn sein Register nicht Null ist, dekrementiert es es und übergibt die Steuerung an den ersten Nachfolger; Andernfalls (dh das Register ist Null) übergibt es die Steuerung einfach an den zweiten Nachfolger.
Für "Nizza" als Programmiersprache benötigen die Endzustände eine fest codierte Zeichenfolge, um gedruckt zu werden (sodass Sie auf eine außergewöhnliche Beendigung hinweisen können).
Die Eingabe erfolgt von stdin. Das Eingabeformat besteht aus einer Zeile pro Status, gefolgt vom Anfangsregisterinhalt. Die erste Zeile ist der Ausgangszustand. BNF für die Landesgrenzen ist:
line ::= inc_line
| dec_line
inc_line ::= label ' : ' reg_name ' + ' state_name
dec_line ::= label ' : ' reg_name ' - ' state_name ' ' state_name
state_name ::= label
| '"' message '"'
label ::= identifier
reg_name ::= identifier
Die Definition von Bezeichner und Nachricht ist flexibel. Ihr Programm muss eine nicht leere alphanumerische Zeichenfolge als Bezeichner akzeptieren , es kann jedoch auch allgemeinere Zeichenfolgen akzeptieren, wenn Sie dies bevorzugen (z. B. wenn Ihre Sprache Bezeichner mit Unterstrichen unterstützt und dies für Sie einfacher ist). In ähnlicher Weise für die Nachrichten Sie müssen eine nicht leere Zeichenfolge von alphanumerischen Zeichen und Leerzeichen akzeptieren, aber Sie können komplexere Strings akzeptieren , die maskierten Newlines und doppelte Anführungszeichen zulassen , wenn Sie wollen.
Die letzte Eingabezeile, die die Anfangsregisterwerte enthält, ist eine durch Leerzeichen getrennte Liste von Zuweisungen von bezeichner = int, die nicht leer sein dürfen. Es ist nicht erforderlich, dass alle im Programm genannten Register initialisiert werden: Alle nicht initialisierten Register werden als 0 angenommen.
Ihr Programm sollte die Eingabe lesen und den RM simulieren. Wenn es einen Beendigungszustand erreicht, sollte es die Nachricht, eine neue Zeile und dann die Werte aller Register (in jeder geeigneten, für den Menschen lesbaren, formatierten und beliebigen Reihenfolge) ausgeben.
Hinweis: Formal sollten die Register unbegrenzte ganze Zahlen enthalten. Sie können jedoch davon ausgehen, dass der Wert eines Registers niemals 2 ^ 30 überschreitet.
Einige einfache Beispiele
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Erwartete Ergebnisse:
Ok
a=0 b=7
b + = a, t = 0
init : t - init d0
d0 : a - d1 a0
d1 : b + d2
d2 : t + d0
a0 : t - a1 "Ok"
a1 : a + a0
a=3 b=4
Erwartete Ergebnisse:
Ok
a=3 b=7 t=0
Testfälle für schwieriger zu analysierende Maschinen
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Erwartete Ergebnisse:
t is 1
t=1
und
s0 : t - "t is nonzero" "t is zero"
t=1
Erwartete Ergebnisse:
t is nonzero
t=0
Ein komplizierteres Beispiel
Entnommen aus der Josephus-Problemcode-Herausforderung des DailyWTF. Die Eingabe ist n (Anzahl der Soldaten) und k (Vorrücken) und die Ausgabe in r ist die (durch Nullen indizierte) Position der Person, die überlebt.
init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3
Erwartete Ergebnisse:
Ok
i=40 k=3 n=0 r=27 t=0
Das Programm als Bild für diejenigen, die visuell denken und es hilfreich finden, die Syntax zu verstehen:
Wenn Sie dieses Golfspiel mögen, schauen Sie sich die Fortsetzung an .
quelle
Antworten:
Perl, 166
Laufen Sie mit
perl -M5.010 file
.Es begann völlig anders, aber ich fürchte, es hat sich gegen Ende in vielen Bereichen der Ruby-Lösung angenähert. Rubys Vorteil scheint "keine Siegel" und Perls "bessere Integration von Regex" zu sein.
Ein bisschen Detail aus den Innereien, wenn Sie Perl nicht lesen:
@p=<>
: Lesen Sie die gesamte Maschinenbeschreibung zu@p
/=/,$_{$`}=$' for split$",pop@p
: Suchen Sie für jede (for
) Zuweisung (split$"
) in der letzten Maschinenbeschreibungszeile (@p
) das Gleichheitszeichen (/=/
) und weisen Sie dann$'
dem Hash-%_
Schlüssel einen Wert zu$`
$o='\w+'
: Anfangszustand wäre der erste, der mit Perl-Regex "Wortzeichen" übereinstimmtuntil/"/
: Schleife, bis wir einen Beendigungsstatus erreichen:map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p
: loop on machine description@p
: Wenn wir in der Zeile sind, die dem aktuellen Status (if/^$o :/
) entspricht, tokenize (/".*?"|\S+/g
) den Rest der Zeile$'
für Variablen($r,$o,$,,$b)
. Trick: Dieselbe Variable,$o
wenn sie ursprünglich für den Markennamen und anschließend für den Operator verwendet wird. Sobald das Label übereinstimmt, überschreibt der Operator es und da ein Label (vernünftigerweise) nicht mit + oder - benannt werden kann, stimmt es nie wieder überein.$_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,
:- Passen Sie das Zielregister nach
$_{$r}
oben oder unten an (ASCII-Magie:','cmp'+'
ist 1, während','cmp'-'
-1 ist);- wenn das Ergebnis negativ ist (
<0?
kann nur passieren für -)- dann bleib bei 0 (
$_{$r}=0
) und gib das zweite Etikett zurück$b
;- Anderenfalls senden Sie das erste (möglicherweise einzige) Etikett zurück
$,
$,
stattdessen$a
so, dass esuntil
ohne Leerzeichen dazwischen auf das nächste Token geklebt werden kann .say for eval,%_
: dump report (eval
) und Inhalt der Register in%_
quelle
/^$o :/
. Das Caret allein reicht aus, um sicherzustellen, dass Sie nur Etiketten betrachten.$'
. Es ist ein Charakter in der Regex, es wären drei$c,
, die von außen zu berücksichtigen sind. Alternativ wechseln einige größere noch zum Tokenizing Regex.Python + C, 466 Zeichen
Nur zum Spaß, ein Python-Programm, das das RM-Programm nach C kompiliert und dann das C kompiliert und ausführt.
quelle
main
', 'if
' usw. haben.Haskell, 444 Zeichen
Mann, das war schwer! Die ordnungsgemäße Bearbeitung von Nachrichten mit Leerzeichen kostet mehr als 70 Zeichen. Die Ausgabeformatierung, die für den Menschen besser lesbar ist und mit den Beispielen übereinstimmt, kostet weitere 25 Euro.
quelle
where
nacheinander in eine einzelne Zeile setzen, die durch Semikolons getrennt ist, können Sie 6 Zeichen sparen. Und ich vermute, Sie könnten ein paar Zeichen in der Definition von sparen,q
indem Sie das ausführliche Wenn-Dann-Sonst in einen Pattern Guard ändern."-"
in der Definitionq
eines Unterstrichs enthalten ist und verwenden Sie stattdessen einen Unterstrich.q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d
. Aber trotzdem ist dieses Programm extrem gut golfen.lex
das Prelude nutzen. Zum Beispiel wird so etwas wief[]=[];f s=lex s>>= \(t,r)->t:f r
eine Zeile in Token aufgeteilt, während die in Anführungszeichen gesetzten Zeichenfolgen korrekt behandelt werden.Ruby 1.9,
214212211198195192181175173175quelle
Delphi, 646
Delphi bietet nicht viel in Bezug auf das Aufteilen von Strings und Sachen. Glücklicherweise haben wir generische Sammlungen, was ein bisschen hilft, aber dies ist immer noch eine ziemlich umfangreiche Lösung:
Hier die eingerückte und kommentierte Version:
quelle
PHP,
446441402398395389371370366 ZeichenUngolfed
Änderungsprotokoll
446 -> 441 : Unterstützt Saiten für den ersten Zustand, und einige leichte Kompression
441 -> 402 : Compressed if / else und Zuweisungsanweisungen so viel wie möglich
402 -> 398 : Funktionsnamen können als Konstanten verwendet werden , die als Zeichenketten verwendet werden können ,
398 -> 395 : Verwendet Kurzschluss Operatoren
395 -> 389 : Keine Notwendigkeit für den anderen Teil
389 -> 371 : Keine Notwendigkeit zur Verwendung array_key_exists ()
371 -> 370 : entfernt nicht benötigter Raum
370 -> 366 : entfernt zwei nicht benötigte Räume in der foreach
quelle
Groovy, 338
quelle
.sort()
)println
!Clojure (344 Zeichen)
Mit ein paar Zeilenumbrüchen für "Lesbarkeit":
quelle
Postscript () ()
(852)(718)Für dieses Mal echt. Führt alle Testfälle aus. Es ist weiterhin erforderlich, dass das RM-Programm sofort im Programmstrom folgt.
Edit: Mehr Factoring, reduzierte Prozedurnamen.
Mit angefügtem Programm eingerückt und kommentiert.
quelle
regline
? Können Sie nicht viel sparen, indem Sie sie Dinge wie nennenR
?AWK - 447
Dies ist die Ausgabe für den ersten Test:
quelle
Stax ,
115100 BytesFühren Sie es aus und debuggen Sie es
quelle