7 , 410 Zeichen, 154 Bytes in der Kodierung von 7, 0 Buchstaben = Punktzahl 154
55104010504200144434451510201304004220120504005434473340353241135014335450302052254241052253052244241052335452241114014241310052340435303052335442302052335500302052335430302052313340435303135014243241310335514052312241341351052302245341351525755102440304030434030421030442030424030455733413512410523142410523030523112411350143355142410523414252410523102410523002410523413342411145257551220304010420030455741403
Probieren Sie es online!
In einer Herausforderung, die es nicht mag, Buchstaben zu benutzen, welche Sprache ist besser als eine, die nur aus Ziffern besteht?
Dies ist ein vollständiges Programm, das über einen Absturz beendet wird. Daher wird stderr nicht korrekt ausgegeben, aber stdout ist korrekt.
Erläuterung
Ein 7-Programm schiebt bei seiner ersten Iteration einfach eine Reihe von Elementen in den Stapel (da von den 12 Befehlen, die in 7 vorhanden sind, nur 8 in einem Quellprogramm dargestellt werden können und diese 8 auf das Schreiben von Code spezialisiert sind) bestimmte Datenstrukturen in den Stack zu verschieben). Dieses Programm verwendet den 6
Befehl nicht (dies ist die einfachste Methode zum Erstellen verschachtelter Strukturen, tritt jedoch ansonsten in einem Quellprogramm nicht buchstäblich auf), sodass nur die 7
Befehle die Struktur bestimmen. 7
schiebt ein neues an die Oberseite des Stapels leeres Element (während der 0
... 5
Befehle an die Oberseite des Stapels gerade append). Wir können dem Programm also Leerzeichen hinzufügen, um seine Struktur zu zeigen:
551040105042001444344515102013040042201205040054344 7
33403532411350143354503020522542410522530522442410523354522411140142413100523
40435303052335442302052335500302052335430302052313340435303135014243241310335
514052312241341351052302245341351525 7
55102440304030434030421030442030424030455 7
334135124105231424105230523112411350143355142410523414252410523102410523002
41052341334241114525 7
551220304010420030455 7
41403
Die Elemente gegen Ende des Programms werden zuletzt verschoben, befinden sich also zu Beginn der zweiten Iteration oben auf dem Stapel. Bei dieser Iteration und allen zukünftigen Iterationen erstellt der 7-Interpreter automatisch eine Kopie der obersten Ebene des Stapels und interpretiert sie als Programm. Das Literal 41403
drückt den (nicht-literalen, Live-Code) 47463
(7 hat 12 Befehle, aber nur 8 von ihnen haben Namen. Als solches verwende ich Fett, um den Code anzuzeigen, und Nicht-Fett, um das Literal anzuzeigen, das diesen Code erzeugt, was bedeutet 4
Dies ist zB der Befehl, der 4
an das oberste Stapelelement angehängt wird . Das Programm, das bei der zweiten Iteration ausgeführt wird, lautet also 47463
. Das bewirkt Folgendes:
47463
4 Swap obere zwei Stapelelemente, ein leeres Element in Between
7 ein leeres Stapelelement nach oben von Stack In
4 Swap oberen zwei Stapelelemente, ein leeres Element dazwischen hinzufügen
6 auszuarbeiten, die Befehle , das obere Stapelelement erzeugen würden;
Hänge das an das Element darunter an (und platziere die alte Oberseite des Stapels)
3 Geben Sie das oberste Stapelelement aus und platzieren Sie das Element darunter
Dies ist einfacher zu verstehen, wenn wir uns ansehen, was mit dem Stapel passiert:
- … D c b einen
47463
(Code auszuführen: 47463
)
- … D c b
47463
entleeren einen (Code auszuführen: 7463
)
- ... d c b entleeren einen leeren (Code auszuführen: )
47463
463
- ... d c b leer leer leer a (Code auszuführen: )
47463
63
- ... d c b leer leer " ein " (Code auszuführen: )
47463
3
- … D c b leer (auszuführender Code: leer )
47463
Mit anderen Worten, wir nehmen die Spitze des Stapels a , ermitteln, welcher Code ihn wahrscheinlich erzeugt hat, und geben diesen Code aus. Der Interpreter 7 fügt am Ende einer Iteration automatisch leere Elemente von der Stapeloberseite ein, sodass die 47463
Rückseite auf der Stapeloberseite angezeigt wird, genau wie im ursprünglichen Programm. Es sollte einfach zu sehen sein, was als nächstes passiert: Wir durchlaufen jedes Stack-Element nacheinander und geben alle aus, bis der Stack unterläuft und das Programm abstürzt. Wir haben also im Grunde genommen eine einfache Ausgabeschleife erstellt, die den Quellcode des Programms überprüft , um zu bestimmen, was ausgegeben werden soll (wir geben nicht die Datenstrukturen aus, die von unserem Computer auf den Stack übertragen wurden) 0
.5
Stattdessen erstellen wir neu, welche Befehle verwendet wurden, indem wir uns ansehen, welche Strukturen erstellt wurden, und diese ausgeben. Somit ist der erste Teil der Datenausgabe 551220304010420030455
(der Quellcode, der das zweitoberste Stapelelement generiert), der zweite 3341351…114525
(der Quellcode, der das drittoberste Stapelelement generiert) und so weiter.
Offensichtlich werden diese Teile des Quellcodes jedoch nicht unverschlüsselt ausgegeben. 7 enthält mehrere verschiedene domänenspezifische Sprachen für die Codierung der Ausgabe. Sobald eine domänenspezifische Sprache ausgewählt wurde, bleibt sie in Gebrauch, bis sie explizit gelöscht wird. Wurde jedoch noch keine der Sprachen ausgewählt, bestimmt die erste Ziffer des ausgegebenen Codes, welche der Sprachen verwendet werden soll. In diesem Programm werden nur zwei Sprachen verwendet:551
und 3
.
551
ist ziemlich einfach: Es ist im Grunde der alte Baudot- / Teletyp-Code, der zum Übertragen von Buchstaben über Teletypen verwendet wird, als 5-Bit-Zeichensatz, der jedoch so geändert wurde, dass alle Buchstaben in Kleinbuchstaben geschrieben werden. Der erste auszugebende Codeabschnitt dekodiert also wie folgt:
551 22 03 04 01 04 20 03 04 55
c a SP e SP n a SP reset output format
Wie zu sehen ist, passen wir jedes Zeichen in zwei Oktalziffern an, was ein ziemlich anständiges Komprimierungsverhältnis darstellt. Zahlenpaare im Bereich von 0 bis 5 geben uns 36 Möglichkeiten, im Gegensatz zu den 32 Möglichkeiten, die Baudot benötigt. Die restlichen vier werden für spezielle Befehle verwendet. in diesem Fall die55
am Ende das gespeicherte Ausgabeformat gelöscht, sodass wir für die nächste Ausgabe ein anderes Format verwenden können.
3
ist konzeptionell noch einfacher, aber mit einer Wendung. Die Grundidee ist, Gruppen von drei Ziffern zu nehmen (ebenfalls im Bereich 0-5, da dies die Ziffern sind, für die wir garantieren können, dass wir den ursprünglichen Quellcode aus seiner Ausgabe wiederherstellen können) und sie als dreistellig zu interpretieren nummerieren Sie in der Basis 6 und geben Sie es einfach als Byte in binärer Form aus. Die Verdrehung ergibt sich jedoch aus der Tatsache, dass die Basis 6 nur 216 dreistellige Zahlen (mit möglichen führenden Nullen) enthält, aber 256 mögliche Bytes. 7 umgeht dies, indem Zahlen von 332₆ = 128₁₀ aufwärts mit zwei verschiedenen Bytes verknüpft werden;332
kann entweder Byte 128 oder 192, 333
Byte 129 oder 193 usw. ausgeben , bis zu 515
welchem Byte Byte 191 oder 255 ausgegeben werden .
Woher weiß das Programm, welche der beiden Möglichkeiten ausgegeben werden soll? Es ist möglich, Drillinge von Ziffern aus zu verwenden520
abwärts zu verwenden, um dies explizit zu steuern, aber in diesem Programm müssen wir Folgendes nicht tun: 7 wählt standardmäßig alle mehrdeutigen Bytes so aus, dass die Ausgabe UTF-8-gültig ist! Es stellt sich heraus, dass es immer höchstens eine Möglichkeit gibt, dies zu tun. Solange es UTF-8 ist (und das tun wir in diesem Fall), können wir es nur mehrdeutig lassen und das Programm funktioniert trotzdem.
Am Ende jedes 3…
Abschnitts wird 525
das Ausgabeformat zurückgesetzt, sodass wir zum 551
nächsten Abschnitt zurückkehren können.
a
s zu codieren - oder auch nicht, je nachdem, wie viele Buchstaben würde es dauern, weil 20 Zeichen eine wirklich große Strafe sind (obwohl, wenn alles andere durch Bytes bewertet wird, es nicht ganz genau definiert ist ...)!