99 (ausgesprochen "neunundneunzig") ist eine brandneue esoterische Programmiersprache (nicht zu verwechseln mit 99 , beachten Sie die Kursivschrift). Deine Aufgabe bei dieser Herausforderung ist es, einen Dolmetscher für 99 zu schreiben , der so kurz wie möglich ist. Die Einsendung mit den wenigsten Bytes gewinnt. Tiebreaker geht zu dem Beitrag, der zuerst veröffentlicht wurde.
Da diese Frage etwas ausführlicher ist als üblich und ich auf gute Antworten gespannt bin, werde ich meiner Lieblingsantwort eine Prämie von 250 Wiederholungen gewähren (nicht unbedingt der Gewinner).
99 spez
99 ist eine imperative Sprache. Jede Zeile in einem 99- Programm ist eine einzelne Anweisung , und während der Ausführung beginnt der Befehlszeiger in der obersten Zeile und durchläuft die nachfolgenden Zeilen nacheinander, wobei er sie auf dem Weg ausführt. Das Programm endet, wenn die letzte Zeile ausgeführt wurde. Goto- Anweisungen können den Pfad des Befehlszeigers umleiten.
Zeilenumbruch, Leerzeichen und 9
sind die einzigen drei Zeichen, die in einem 99- Programm eine Rolle spielen . Alle anderen Zeichen werden vollständig ignoriert. Darüber hinaus werden nachfolgende Leerzeichen in jeder Zeile ignoriert und mehrere Leerzeichen in einer Zeile werden als ein Leerzeichen gelesen. ("Newline" bezieht sich auf alle gängigen Zeilenumbruchkodierungen . Es spielt keine Rolle, welchen Ihr Interpreter verwendet.)
Also dieses Programm:
9 BLAH 99 9a9bb9c9
9 this line and the next have 6 trailing spaces 9
Ist identisch mit diesem Programm:
9 99 9999
9 9
Variablen
Variablen in 99 haben alle Namen, 9
die aneinander 9+
gereiht sind ( in Regex). Beispielsweise sind 9
, 99
und 9999999999
alle unterschiedliche Variablen. Natürlich gibt es unendlich viele (außer Speicherbeschränkungen).
Der Wert jeder Variablen ist eine vorzeichenbehaftete Ganzzahl mit beliebiger Genauigkeit . Standardmäßig ist jede Variable einer eigenen numerischen Darstellung zugeordnet. Sofern es nicht neu zugewiesen wurde, ist der Wert der Variablen 9
die Zahl 9 und der Wert der Variablen 99
die Zahl 99 und so weiter. Sie können sich vorstellen, dass die Variablen als reine Zahlen behandelt werden, bis sie explizit zugewiesen werden.
Ich werde V
unten auf einen beliebigen Variablennamen verweisen.
Jede Instanz V
könnte ersetzt werden 9
, 99
, 999
, 9999
etc.
Aussagen
Es gibt fünf verschiedene Anweisungstypen in 99 . Jede Zeile in einem 99- Programm enthält genau eine Anweisung.
Bei der hier beschriebenen Syntax wird davon ausgegangen, dass alle überflüssigen Zeichen entfernt wurden, alle nachgestellten Leerzeichen entfernt wurden und alle Folgen mehrerer Leerzeichen durch einzelne Leerzeichen ersetzt wurden.
1. Keine Operation
Eine leere Zeile ist ein No-Op . Es tut nichts (außer den Befehlszeiger zu erhöhen).
2. Ausgabe
V
Eine einzelne Variable V
in einer Zeile gibt diese Variable als Standardausgabe aus.
Wenn V
es eine ungerade Zahl von 9
's ( 9
, 999
usw.) gibt, wird der ganzzahlige Wert V
geteilt durch 9 (in Dezimalzahl) ausgegeben.
Wenn V
es eine gerade Anzahl von 9
's ( 99
, 9999
usw.) gibt, wird das ASCII- Zeichen mit dem V
durch 9 geteilten Code , Mod 128, gedruckt. (Das ist (V / 9) % 128
ein Wert von 0 bis 127.)
Beispiel : Das Programm
9
9999
würde drucken 1W
. Die erste Zeile wird gedruckt, 1
weil 9/9 1 ist. Die zweite Zeile wird gedruckt, W
weil 9999/9 1111 ist und 1111 mod 128 87 ist und 87 der Zeichencode für ist W
.
Beachten Sie, dass zwischen Ausgabe-Token keine Zeilenumbrüche gedruckt werden. \n
muss für einen Zeilenumbruch explizit gedruckt werden.
3. Eingabe
V
Eine einzelne Variable V
in einer Zeile mit einem führenden Leerzeichen nimmt die Eingabe von stdin entgegen und speichert sie in dieser Variablen.
Wenn V
es eine ungerade Anzahl von 9
's gibt, kann der Benutzer eine beliebige vorzeichenbehaftete Ganzzahl eingeben und V
wird auf das 9-fache dieses Werts gesetzt.
Wenn V
es eine gerade Anzahl von 9
's gibt, kann der Benutzer ein beliebiges ASCII- V
Zeichen eingeben und wird auf das 9-fache seines Zeichencodes gesetzt.
Beispiel : Gegeben -57
und A
als Eingabe dieses Programm
9
9
99
99
würde ausgeben -57A
. Intern hätte die Variable 9
den Wert -513 und 99
den Wert 585.
Ihr Interpreter kann davon ausgehen, dass die Eingaben immer syntaktisch gültig sind.
4. Abtretung
Diese Aussage kann beliebig lang sein. Es sind zwei oder mehr Variablen in einer Zeile, die durch Leerzeichen getrennt sind:
V1 V2 V3 V4 V5 ...
Dies wird der Summe aller Indizes mit geraden Indizes abzüglich der Summe der Indizes mit ungeraden Indizes (ausgenommen ) zugewiesen . Zuweisungen sind nach Wert und nicht nach Referenz.V1
V
V
V1
Es könnte in die meisten Sprachen übersetzt werden als .V1 = V2 - V3 + V4 - V5 + ...
Wenn es also nur zwei Variablen gibt, ist dies eine normale Zuweisung:
V1 V2
→ V1 = V2
Wenn es drei gibt, dann ist es Subtraktion:
V1 V2 V3
→ V1 = V2 - V3
Und das +
/ -
-Zeichen wechselt mit jeder weiteren Variablen hin und her:
V1 V2 V3 V4
→ V1 = V2 - V3 + V4
Beispiel : Dieses Programm würde Folgendes ausgeben 1110123
:
999 Prints triple-nine divided by nine (111).
999 9 9 Assigns triple-nine to zero (nine minus nine).
999 Prints triple-nine divided by nine (0)
9 999 9 Assigns single-nine to negative nine (zero minus nine).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (1).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (2).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (3).
5. Springen (springe wenn alles Null ist)
Diese Aussage kann auch beliebig lang sein. Es sind zwei oder mehr Variablen in einer durch Leerzeichen getrennten Zeile mit einem führenden Leerzeichen :
V1 V2 V3 V4 V5 ...
Wenn einige der Werte ungleich Null sind, verhält sich dies wie ein No-Op. Der Anweisungszeiger wird wie gewohnt in die nächste Zeile verschoben.V1
Wenn alle der Werte außer sind Null, dann wird der Befehlszeiger bewegt Nummer Zeile . Die Zeilen sind mit einem Index von Null versehen. Wenn also Null ist, bewegt sich der Zeiger zur obersten Zeile. Das Programm wird (normalerweise ohne Fehler) beendet, wenn es negativ oder größer als der höchstmögliche Index ist (Anzahl der Zeilen minus eins).V1
V1
V1
V1
Beachten Sie, dass hier nicht durch 9 geteilt wurde. Und da es unmöglich ist, eine Variable als Wert zu definieren, der kein Vielfaches von 9 ist, kann nur zu Zeilennummern gesprungen werden, die ein Vielfaches von 9 sind.V1
Beispiele:
Dieses Programm wird für immer drucken 1
:
9 Prints single-nine divided by nine (always 1).
99 9 9 Assigns double-nine to zero.
99 99 Jumps to line zero (top line) if double-nine is zero.
Dieses Programm
99999999 Print G.
999 99 Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999 Set 10-nine to zero.
99999999999 9999999999 Set 11-nine to zero.
999 Print triple-nine's value divided by nine. (This is the ninth line.)
99999999 Print G.
999 999 9 Subtract nine from triple-nine.
99999 999 Jump to line 5-nines if triple-nine is zero (ends program).
9 99999999999 9999999999 Jump to line nine if 10-nine and 11-nine are zero (always jumps).
gibt die Zahlen 11 bis 1 in absteigender Reihenfolge aus, umgeben von G
:
G11G10G9G8G7G6G5G4G3G2G1G
Zusätzliche Details
Der ideale Interpreter wird von der Befehlszeile aus mit dem Namen der 99- Programmdatei als Argument ausgeführt. Die E / A-Vorgänge werden auch direkt in der Befehlszeile ausgeführt.
Sie können jedoch einfach eine Interpreterfunktion schreiben, die das Programm als Zeichenfolge sowie eine Liste der Eingabe-Token (z ["-57", "A"]
. B. ) aufnimmt . Die Funktion sollte die Ausgabezeichenfolge drucken oder zurückgeben.
Etwas andere Methoden zum Ausführen des Interpreters und zum Behandeln von E / A sind in Ordnung, wenn diese Optionen in Ihrer Sprache nicht möglich sind.
Bonus: Schreibe etwas Cooles in 99 und ich werde es gerne in diesen Beitrag als Beispiel setzen.
- Hier ist ein Pastebin eines ordentlichen "99 Bottles of Beer" -Programms aus Macs Antwort .
Hoffe, du hast meine 99. Herausforderung genossen ! : D
quelle
Antworten:
CJam, 157 Bytes
Probieren Sie es online aus:
Erläuterung
Der Versuch, dies mit den richtigen Einrückungen und Kommentaren zu formatieren, würde wahrscheinlich ewig dauern, daher gebe ich nur eine algorithmische Zusammenfassung.
Der Code ist ein Block, CJam ist analog zu anonymen Funktionen. Der Block erwartet bei der Ausführung die Programmzeichenfolge und die Liste der Eingaben auf dem Stapel.
Die Initialisierung besteht aus drei Schritten. Zunächst wird die Eingabeliste gespeichert. Dann wird jedes Zeichen im Programm, das nicht aussagekräftig ist, entfernt und das Ergebnis in eine Liste von Zeilen aufgeteilt und gespeichert. Zuletzt wird die Variablenliste initialisiert. Diese Liste ordnet jede Variable, die nach der Länge des Namens indiziert ist, ihrem durch 9 geteilten Wert zu (eine Variable kann niemals einen Wert enthalten, der kein Vielfaches von 9 ist, und alle Operationen außer goto profitieren von dieser Änderung). Die Liste wird bis zur Länge der längsten Zeile initialisiert, die eine Obergrenze für den längsten vorhandenen Variablennamen darstellt. Es gibt auch eine gewisse implizite Initialisierung aufgrund der anfänglichen Variablenwerte: Die Zeilennummer ist 0 und der Eingabeindex ist -1.
Der Interpreter wird wie erwartet implementiert: Eine Schleife, die die nächste Zeile liest, die Zeilennummer erhöht und die Zeile ausführt, während die Zeilennummer auf eine vorhandene Zeile zeigt. Bei der Zeilenanalyse wird zunächst überprüft, ob die Zeile nicht leer ist. Anschließend werden Verzweigungen basierend darauf ausgeführt, ob die Arität 1 oder> 1 ist. Anschließend werden Verzweigungen basierend darauf ausgeführt, ob ein führendes Leerzeichen vorhanden war. Diese vier Zweige emulieren die vier Operationen (ohne No-Op) auf meist unkomplizierte Weise, obwohl sie wie alles andere aggressiv golfen. Vielleicht ist eine Optimierung der Anmerkung, dass, da eine gültige Eingabesequenz immer ein Element des vom Programm erwarteten Typs erzeugen sollte, ich es unterlassen habe, separate Eingabefälle basierend auf der Länge des Variablennamens zu erstellen. Es wird einfach angenommen, dass das aus der Eingabeliste gelesene Element vom erwarteten Typ ist.
quelle
128%
mit128,=
.Python 3,
421414410404388395401 BytesGolf gespielt:
Ungolfed:
Im Grunde genommen nur eine wörtliche Umsetzung der Spezifikation, soweit ich das beurteilen kann.
Führen Sie den Befehl über die Befehlszeile aus, indem Sie eine 99-Quellcodedatei als einziges Argument angeben (z. B. das letzte Beispiel aus dem OP):
Als zusätzlichen Bonus gibt es hier eine (ziemlich schlechte) Implementierung von "99 Flaschen" in 99 : http://pastebin.com/nczmzkFs
quelle
else
nach einer Nummer entfernt werden konnte, aber als ich es früher versuchte, bekam ich einen Syntaxfehler. Ihre anderen Tipps werden jedoch sehr geschätzt!goto
Routine und beim Abrufen des Standardwerts der Variablen). Für einen Sprachanwender macht dies keinen Unterschied.else
Selbst, nur der Raum davor. Eg3*n+1if n%2else n//2
.else
. Zum Beispiel habe ich versucht , Ersatzprint(w if L(e)%2 else chr(w%128))
mitprint(w if L(e)%2else chr(w%128))
und bekam Ausnahme eine Syntax.e
oder beginnenE
, und (aus den Kommentaren) auch nicht für0or
beide.Common Lisp,
1180857837836 BytesIch weiß, das wird nicht gewinnen, aber ich hatte Spaß beim Golfen. Ich konnte 343 Bytes entfernen, das sind mehr als zwei 99 Interpreter, die in CJam geschrieben wurden.
Außerdem ist es ziemlich amüsant, je mehr ich versuche, es zu komprimieren, desto mehr bin ich überzeugt, dass es für Common Lisp kürzer ist , den Code zu kompilieren, als ihn im laufenden Betrieb zu interpretieren.
Es gibt eine einzige
tagbody
, die 2 Schleifen ausführt:lokale Variablen werden in deklariert
&aux
Ungolfed, kommentierte
Bei der Auswertung wird die Standardeingabe / -ausgabe verwendet, dh Standard
read
undprinc
Funktionen werden verwendet. Daher kann der resultierende Code in der Befehlszeile ausführbar gemacht werden (siehe unten).Eingaben werden bei der Ausführung von 99 Programmen nicht vollständig bereinigt : Es wird davon ausgegangen, dass der Benutzer weiß, welche Werte erwartet werden.
Der einzig mögliche Laufzeit- Overhead kann beim Springen auftreten, da wir den Wert einer Variablen auswerten und diesen Wert einer Beschriftung zuordnen müssen. Abgesehen davon muss der Dolmetscher sehr effizient sein.
Basierend auf der cleveren Beobachtung von Mac, dass wir nicht jedes Mal 9 dividieren und multiplizieren müssen, schafft es die aktuelle Version, während der Ausführung niemals 9 zu dividieren oder zu multiplizieren.
Beispiel
Wenn wir ersetzen
defmacro
durchdefun
, sehen wir den generierten Code. Zum Beispiel:Hier ist der resultierende Code:
Bei Ausführung wird "G11G10G9G8G7G6G5G4G3G2G1G" gedruckt.
Befehlszeile
Wir können eine ausführbare Datei erstellen, indem wir einen Core sichern und die
toplevel
Funktion angeben . Definieren Sie eine Datei mit dem Namen,boot.lisp
in der Sie die ablegendefmacro
, und schreiben Sie Folgendes:Laufen
sbcl --load boot.lisp
gibt die folgende Ausgabe aus:Führen Sie dann das kompilierte 99- Programm aus:
99 Flaschen
Wenn Sie interessiert sind, finden Sie hier den kompilierten Code für das 99-Flaschen-Programm, der in Macs Antwort geschrieben ist : http://pastebin.com/ZXe839CZ (dies ist die alte Version, in der wir Lambda und hübschere Arithmetik verwenden
jmp
undend
kennzeichnen).Hier ist eine Ausführung mit der neuen Version, um zu beweisen, dass sie immer noch funktioniert: http://pastebin.com/raw.php?i=h73q58FN
quelle
TI-84 Basic (Calculator Script),
376373377381 ByteWenn es auf einem TI-84-Rechner läuft, können Sie es für einen standardisierten Test verwenden ... also ist es nützlich;)
Minimale Betriebssystemversion - 2.53MP (MathPrint) aufgrund des Summensigmas
PS-ASCII-Richtlinien konnten nicht genau befolgt werden, aber in TI-Basic
:
steht ein Zeilenumbruch. Somit bedeuten alle tatsächlichen Zeilenumbrüche im Code, dass die:
oder#
am Anfang jeder Zeile nicht erforderlich sind. Die ersten Token:
und#
unterscheiden nur zwischen Kommentaren und Code.Original Hex Dump (376 Bytes)
Edit # 1 - Optimiert 3 Bytes mit Macs Beobachtung. Edit # 2 & # 3 - Behobene Fehler, die von Runer112 entdeckt wurden.
quelle
#
für die Kommentare zu verwenden? (Anmerkung: Kommentare im aktuellen Code werden als Zeile mit nur einer nicht geschlossenen Zeichenfolge implementiert, die Ans überfordert.)Ans
Eingabe wird überschrieben, sodassAns->Str0
in Zeile 6 ein Fehler auftritt. In mehreren Fällen kann das Längenargument einessub()
Befehls Null sein, was zu einem Fehler führt. InAns
Zeile 11 wird ein String angezeigt soAns-J
wird fehler ... und ich habe nur über die erste hälfte des programms geschaut.sub()
Befehl die Länge Null haben und einen Fehler auslösen kann. Und sobald diesub()
Beschwerden behoben sind, kann es leider weitere Probleme geben.9
die Zahl 9 und der Wert der Variablen99
die Zahl 99. und so weiter." Und Zeichenfolgen der Länge 0 können mit ähnlichen Mitteln erzeugt werden""
, aber es ist eine Art Fehler, den im Grunde kein Zeichenfolgenmanipulationsbefehl verbrauchen oder eine leere Zeichenfolge erzeugen kann, einschließlichsub()
.C 426
458 481 497Bearbeiten Vielleicht gehe ich zu weit, aber das funktioniert mit Visual C: stdio.h wurde entfernt, wobei int anstelle von FILE * für fopen und getc verwendet wurde
Bearbeiten 2 Ausführungsschritt neu ordnen, mehr Unordnung, 32 Zeichen gespeichert
Eigenständiges Konsolenprogramm, Programmname in der Befehlszeile und Eingabe / Ausgabe über die Konsole.
Alter K & R-Stil, Standardtyp int für globale Variablen und Parameter. Angenommen, EOF ist als -1 definiert (wie in jeder mir bekannten C-Implementierung).
Kompiliert mit Warnungen mit Visual Studio 2010 (Win32-Konsolen-C ++ - Projekt, kompiliert als C) Kompiliert auf Ideone, kann jedoch nicht ausgeführt werden, da es eine Datei benötigt.
Im ersten Schritt wird der Quellcode gelesen und analysiert. Jede Zeile wird als Folge von ganzen Zahlen gespeichert, basierend auf den Zahlen von 9s. Wenn ein führendes Leerzeichen vorhanden ist, ist die erste Zahl negativ. Also:
9 BLAH 99 9a9bb9c9
(9 99 9999
) wird-1,2,4
Es gibt eine Abkürzung - nicht so legal: Alle ASCII-Codes, die kleiner als '' sind, werden als Zeilenumbrüche betrachtet.In diesem Schritt werden alle verwendeten Variablen vorinitialisiert.
Der Ausführungsschritt folgt den Vorgaben, ohne Schnickschnack, und speichert Zahlen geteilt durch 9.
Mehr lesbaren gleichen Code (ich hoffe), Leerzeichen und Zeilenumbrüche hinzugefügt
quelle
Haskell, 550 Bytes
Beispiellauf mit dem in der Datei gespeicherten "Countdown" -Programm
i.99
Ungolfed-Version:
quelle
JavaScript (ES6) 340
352Eine Funktion mit 2 Parametern
Der dritte optionale Parameter (Standard 10k) gibt die maximale Anzahl von Iterationen an. Ich mag kein Programm, das für immer ausgeführt wird
JSFiddle Zum testen
quelle
q / k,
490469.
Das Skript ist eine Mischung aus q und k, also definiere ich zuerst ein paar q Schlüsselwörter, die ich in k Funktionen mehrmals verwenden möchte. (im Grunde #define Makros)
f
Liest die in das Programm übergebene Datei und entfernt unnötige Zeichenm
Nimmt eine Liste / einen Vektor und multipliziert die ungeraden Indizes mit -1b
ist nur eine leere Funktion, die für die No-Op-Zeilen verwendet wirdp
ist die Druckfunktion.K
ist eine Funktion, die eine Variable untersucht. Wenn die Variable existiert, wird sie zurückgegeben, andernfalls wird nur das Literal zurückgegeben.v
ist die Zuweisungsfunktion.g
ist die goto-Funktion.r
Nimmt eine Zeichenfolge und entscheidet, welche Operation angewendet werden muss.Und zum Schluss iteriere ich einfach durch die
f
Liste der Zeichenfolgen mitn
als Iterator. Die goto-Funktion wirdn
nach Bedarf aktualisiert .quelle
Perl,
273 266 255 244238Zeilenumbrüche zur Verdeutlichung hinzugefügt.
Programmname in Kommandozeile übernommen:
Jede Programmzeile wird in Perl-Code konvertiert, zum Beispiel:
Mehr Details
quelle