2.}<@>%?<{>$"/\M!8;
Lesbar:
2 . }
< @ > %
? < { > $
" / \ M
! 8 ;
Probieren Sie es online!
Dies kann wahrscheinlich durch ein oder zwei Bytes golfen werden, aber das erfordert möglicherweise ein wirklich ausgeklügeltes Layout, das mit brachialer Gewalt leichter gefunden werden kann (selbst wenn es ziemlich lange dauert, es zu finden).
Erklärung auf hohem Niveau
Das Programm folgt meistens diesem Pseudocode:
while (read number is not zero)
{
if (number is even)
print number;
}
Was missbraucht, wie Hexagony versucht, eine Zahl zu lesen, wenn STDIN leer ist (es gibt eine Null zurück). Vielen Dank an Martin für die Hilfe bei der Entwicklung dieses Ansatzes.
Vollständige Erklärung
Ich habe immer noch nicht mit Mono rumgespielt, um Timwis fantastische esoterische IDE zum Laufen zu bringen, also habe ich mich darauf verlassen, dass Martin mir einige hilfreiche, hübsche Bilder liefert!
Zunächst eine kleine Einführung in den grundlegenden Kontrollfluss in Hexagony. Der erste Befehlszeiger (IP), der als einziger in diesem Programm verwendet wird, beginnt oben links im hexagonalen Quellcode und bewegt sich nach rechts. Wenn die IP die Kante des Sechsecks verlässt, werden die side_length - 1
Reihen in Richtung der Mitte des Sechsecks verschoben. Da dieses Programm ein Sechseck mit einer Seitenlänge von drei verwendet, verschiebt sich die IP in diesem Fall immer um zwei Zeilen. Die einzige Ausnahme ist, wenn es sich von der mittleren Reihe wegbewegt, wo es sich abhängig vom Wert der aktuellen Speicherkante bedingt nach oben oder unten im Sechseck bewegt.
Nun ein bisschen zu den Bedingungen. Das einzige in conditionals Hexagony für Steuerfluß ist >
, <
und die mittlere Kante des Sechsecks. Diese folgen alle einer konstanten Regel: Wenn der Wert an der aktuellen Speicherflanke Null ist oder der negative Kontrollfluss sich nach links bewegt und wenn er positiv ist, fließt der Kontrollfluss nach rechts. Die Klammern größer als und kleiner als lenken die IP in Winkeln von 60 Grad um, während die Kante des Sechsecks steuert, zu welcher Zeile die IP springt.
Hexagony hat auch ein spezielles Speichermodell, bei dem alle Daten an den Rändern eines unendlichen hexagonalen Gitters gespeichert werden. Dieses Programm verwendet nur drei Kanten: eine zum Speichern von zwei, eine für die aktuell gelesene Nummer und eine für die Nummer modulo zwei. Es sieht ungefähr so aus:
Mod \ / Input
|
2
Ich werde nicht zu jedem Zeitpunkt während der Erläuterung des Programms sorgfältig erklären, wo wir uns im Speicher befinden. Kommen Sie also hierher zurück, wenn Sie verwirrt sind, wo wir uns im Speicher befinden.
Mit all dem kann die eigentliche Erklärung beginnen. Zuerst füllen wir die "2" -Kante im Speicher mit einer 2, führen dann ein No-Op aus und bewegen den Speicherzeiger nach rechts ( 2.}
).
Als nächstes beginnen wir die Hauptprogrammschleife. Wir lesen die erste Zahl von STDIN und treffen dann eine Bedingung ( ?<
). Wenn in STDIN keine Zahlen mehr vorhanden sind, liest dies eine Null in die aktuelle Speicherflanke, sodass wir nach links auf die abbiegen @
, die das Programm beendet. Andernfalls hüpfen wir von einem Spiegel, bewegen den Speicherzeiger nach hinten und nach links, wickeln uns um das Sechseck, um den Rest der Division der Eingabe durch 2 zu berechnen, und drücken dann eine andere Bedingung ( /"%>
).
Wenn der Rest eins war (dh die Zahl war ungerade), biegen wir nach rechts ab und folgen dem blauen Pfad oben, indem wir das No-Op erneut ausführen. Dann wickeln wir uns bis zum Ende des Sechsecks um, multiplizieren die aktuelle Kante mit 10 und addieren dann Acht, hüpfen Sie von ein paar Spiegeln, multiplizieren und addieren Sie erneut, setzen Sie 188 auf die aktuelle Kante, führen Sie den No-Op erneut aus und beenden Sie schließlich das Programm ( .8/\8.@
). Dieses verworrene Ergebnis war ein glücklicher Zufall, ich hatte ursprünglich ein viel einfacheres Stück Logik geschrieben, aber festgestellt, dass ich es zugunsten des No-Ops entfernen konnte, von dem ich dachte, dass es eher im Sinne von Hexagony war.
Wenn der Rest Null war, biegen wir stattdessen links ab und folgen dem roten Pfad oben. Dies bewirkt, dass wir den Speicherzeiger nach links bewegen und dann den Wert (den Eingabewert) als Zahl ausgeben. Der Spiegel, dem wir begegnen, wirkt aufgrund der Richtung, in die wir uns bewegen, wie ein No-Op ( {/!
). Dann treffen wir die Kante des Sechsecks, die eine Bedingung mit nur einem Ergebnis darstellt, da der Eingabewert von zuvor bereits als positiv getestet wurde, sodass wir uns immer nach rechts bewegen (wenn Sie sich vorstellen, in Richtung der IP zu blicken). . Wir multiplizieren dann die Eingabe mit 10 und addieren zwei, nur um die Richtung zu ändern, wickeln den neuen Wert um und überschreiben ihn mit dem ASCII-Wert des Großbuchstabens M, 77. Dann schlagen wir einige Spiegel und verlassen ihn über den Rand der Mitte von das Sechseck mit einem Trampolin (2<M\>$
). Da 77 positiv ist, bewegen wir uns ganz nach unten und überspringen wegen des Trampolins die erste Anweisung ( !
). Wir multiplizieren dann die aktuelle Speicherflanke mit 10 und addieren 8, um 778 zu erhalten. Wir geben dann diesen Wert mod 256 (10) als ASCII-Zeichen aus, was zufällig Newline ist. Schließlich verlassen wir das Sechseck und kehren zum ersten zurück, ?
der den 778 mit dem nächsten Eingabewert überschreibt.