Das war überraschend schwierig und ich bin nicht überzeugt, dass es optimal ist ...
<.@!$?
Nach dem Auffüllen und Entfalten des Codes stellt dies das folgende Hex-Raster dar:
Dies verwendet einen ähnlichen Steuerungsfluss wie mein kürzlich erstelltes fehlerfreies Katzenprogramm , das sich entlang von Antidiagonalen bewegt. Um dies zu erreichen, lenken wir den Anweisungszeiger (IP) nach links, wobei der violette Pfad in die untere linke Ecke übergeht.
?
Liest die Eingabe als Ganzzahl. !
druckt es zurück. .
ist nur ein No-Op. Jetzt fungiert die Ecke des Rasters als Zweig:
Wenn die Eingabe war 0
, wird die IP auf dem roten Pfad fortgesetzt, wodurch das Programm einfach mit beendet wird @
.
Wenn die Eingabe war 1
, wird die IP auf dem grünen Pfad fortgesetzt. Auch dies .
ist nur ein No-Op, $
entspricht jedoch Befunges Trampolin: Die nächste Anweisung wird übersprungen. Nach dem Umbruch wäre die nächste Anweisung die, die ?
aber aufgrund der $
Ausführung tatsächlich auf dem blauen Pfad fortgesetzt wird, beginnend mit !
dem Drucken einer weiteren Kopie der 1
. Diese Schleife, die nur enthält, !..$
wird jetzt auf unbestimmte Zeit wiederholt.
Eine Studie zum Kontrollfluss in Hexagony ...
Ich halte die obige Lösung für optimal. Ich habe einen Brute Forcer geschrieben, die alle 6-Byte Hexagony Programme überprüft, die mindestens eine jeweils enthalten ?!@
(die notwendig sind , um, ich habe auch überprüft :
und %
anstelle des @
mit einer Division durch Null Fehler zu beenden, aber das hat auch nicht geholfen). Die Prüfung gibt alle Programme aus, die a) 0
bei Eingabe 0
und Beendigung erzeugen und b) mindestens zwei 1
Sekunden (und sonst nichts ) erzeugen und nicht innerhalb der ersten 60 Ticks des Programms enden (200 Ticks für 5-Byte-Lösungen). . Ich bezweifle, dass eine gültige Lösung mehr als 200 Ticks benötigt, um die erste 0
oder die zweite 1
auf einem so kleinen Raster korrekt auszudrucken. Daher habe ich keine potenziellen Lösungen verpasst.
Die Suche ergab keine Ergebnisse für 5 Bytes, aber 57 Ergebnisse für 6 Bytes (mit @
; Sie müssen nicht mit einem Fehler abbrechen, wenn Sie dies sauber in der gleichen Anzahl von Bytes lösen können). Von diesen 57 waren nur 6 falsch positive Ergebnisse, die tatsächlich nur zwei 1
s druckten und dann in eine Endlosschleife eintraten, ohne mehr zu drucken. Eine Lösung wurde zweimal aufgeführt, da sie zwei !
Befehle enthielt . Damit bleiben genau 50 gültige Lösungen.
Es gibt eine gewisse Degeneriertheit zwischen den Lösungen, bei denen ein oder zwei Zeichen nicht wesentlich sind, z. B. weil sie sowieso praktisch keine Aktionen sind. Die Lösungen können in 23 Gruppen von wirklich unterschiedlichen Programmen gruppiert werden (in einigen Fällen gibt es nur einen einzigen Zeichenunterschied zwischen zwei Gruppen, aber dies ändert den Kontrollfluss erheblich, sodass ich sie separat gezählt habe). Zwei der Gruppen verwenden sogar auf sehr unerwartete Weise mehrere Befehlszeiger. Da ich mir die meisten dieser Möglichkeiten, die Äste und Spiegel zu verwenden, niemals ausgedacht hätte, machen sie eine sehr interessante Untersuchung darüber, welche Arten von Kontrollfluss in Hexagony möglich sind, und ich habe definitiv einige neue Tricks für zukünftige Golfer gelernt.
Der gesamte Kontrollfluss ist fast immer der gleiche: Eine Zahl lesen, ausdrucken. Wenn Sie 0
einen Weg zum finden @
, durchlaufen Sie die Schleife, !
während Sie den Kantenwert von beibehalten 1
. Es gibt vier bemerkenswerte Ausnahmen:
- Eine Lösung (die mit zwei
!
) druckt zwei 1
Sekunden pro Iteration durch das Raster und damit ungefähr doppelt so schnell wie die meisten Programme. Ich habe dieses mit x2
unten markiert .
- Einige Lösungen (diejenigen, die ein enthalten
o
) ersetzen das 1
durch ein 111
(den Zeichencode von o
), sodass drei 1
s pro Iteration ausgegeben werden, was sie ungefähr dreimal so schnell wie die meisten Programme macht. Ich habe diese mit x3
unten markiert .
- Zwei Lösungen fügen
1
in jeder Iteration ein an den Kantenwert an (so 1
-> 11
-> 111
-> ...). Diese werden sehr schnell gedruckt , aber ihnen wird irgendwann der Speicher ausgehen. Ich habe diese mit OoM
unten markiert .
- Zwei Lösungen treten in eine sehr enge Schleife ein, die lediglich über den
!
anderen Ticks hin und her springt (anstelle von etwa jedem fünften), wodurch sie etwas schneller (und sauberer) werden. Ich habe diese mit ><
unten markiert .
Also hier ist der gesamte Zoo:
#1 #5 #12 #19
?!/$.@ ?$!>$@ .?!/$@ |!|?$@ # ><
?!/$1@ # OoM ?$!|$@ =?!/$@
?!/$=@ #20
?!/$\@ #6 #13 $@.?<!
?!/$o@ # x3 ?/!<|@ .?/!$@ $@1?<! # OoM
?!/$!@ # x2 =?/!$@ $@=?<!
#7 $@o?<! # x3
#2 ?\!<|@ #14
?!>$)@ \!?__@ #21
?!>$1@ #8 _>_!?@
?!>$o@ # x3 ?<!>$@ # >< #15
?!|$)@ \_?!$@ #22
?!|$1@ #9 <!@.$?
?!|$o@ # x3 ?\$!@$ #16 <!@/$?
\_?!_@ <!@=$?
#3 #10 <$@!$?
?!|)$@ ?~#!@) #17 <.@!$?
?!|1$@ ?~#!@1 $$?\@! </@!$?
?!|o$@ # x3 <=@!$?
#11 #18
#4 ?$)\@! \$?\@! #23
?_!<@> ?$1\@! <<@]!?
?$o\@! # x3
Das Folgende ist eine kurze exemplarische Vorgehensweise für eine Handvoll der repräsentativeren Gruppen. Besonders die Gruppen 10 und 23 sind einen Besuch wert. Es gibt viele andere interessante und manchmal verschlungene Wege in den anderen Gruppen, aber ich denke, ich habe dich am Ende genug gelangweilt. Für alle, die Hexagony wirklich lernen möchten, sind diese definitiv eine Untersuchung wert, da sie noch mehr Verwendungsmöglichkeiten für die Spiegel und aufweisen $
.
Gruppe 1
Dieser ist nicht viel ausgefeilter als meine ursprüngliche Lösung, aber die Wege gehen in verschiedene Richtungen. Es erlaubt auch die größte Anzahl von Variationen in einer einzelnen Zelle, da das No-Op ganz rechts durch 5 verschiedene Befehle ersetzt werden kann, die dies weiterhin gültig machen, ohne die Struktur zu ändern:
Gruppe 2
Dieser ist sehr interessant, weil er sich nur horizontal bewegt. Nach dem Wickeln in die >
kehrt sich die IP sofort um und nimmt den Zweig in der Ecke. Es ist nicht ganz gut sichtbar, kein Diagramm, aber im Falle der 1
wir die erste Reihe wieder durchlaufen, aber diesmal rückwärts. Dies bedeutet auch, dass wir ?
erneut darauf 0
stoßen , was jetzt zurückkehrt (EOF). Dies ist mit )
(Inkrement) festgelegt, um den Druckvorgang 1
fortzusetzen. Dies hat auch 5 Variationen, wie )
auch 1
oder o
, und >
könnte auch sein |
:
Gruppe 3
Dieser sieht fast identisch mit dem vorherigen aus, ist aber höllisch chaotisch. Bis zum Schlagen |
und Überqueren der unteren oder oberen Reihe ist es dasselbe. Aber im Falle einer Schleife $
überspringt die nun )
auf den Spiegel. So folgen wir dem türkisfarbenen Weg nach rechts, jetzt dem Zuwachs getroffen, überspringen die @
bevor wir wickeln um auf die |
wieder und dann auf den grünen Weg an der Spitze zurück.
Gruppe 4
Ich dachte, dass dieser besonders geschickt war:
Der _
Spiegel in der oberen rechten Ecke ist anfangs ein No-Op, also drucken wir mit !
und drücken die <
. Der 0
Pfad trifft jetzt auf den horizontalen Spiegel und endet. Der 1
Weg führt eine wirklich obwohl interessante Bahn: es lenkt ab, um die Wraps !
, wird in Richtung der horizontalen umgeleitet und dann auf die Packungen zurück !
wieder . Es bewegt sich dann weiter in dieser Rhombusform und druckt zweimal pro Iteration (jeder dritte Tick).
Gruppe 8
Dies ist eine der beiden Lösungen mit einer sehr engen Druckschleife:
Der <
fungiert als Abzweig. Nach zweimaligem Umwickeln 0
Treffer @
. 1
Überspringt andererseits zuerst das ?
, und >
sendet es dann $
erneut an das, so dass das übersprungen wird @
. Dann wird die IP in den türkisfarbenen Pfad gewickelt , wo sie zwischen >
und hin und her springt <
(um den Rand dazwischen wickeln).
Gruppe 10
Eine von zwei Gruppen, die andere Anweisungszeiger verwenden, und es ist absolut schön. Hexagony hat 6 - jede beginnt an einer anderen Ecke im Uhrzeigersinn, aber immer nur eine davon ist aktiv.
Wie immer lesen wir mit ?
. Jetzt ~
ist unäre Verneinung: es verwandelt sich 1
in eine -1
. Als nächstes schlagen wir die #
. Dies ist eine Möglichkeit, zwischen IPs zu wechseln: Es wird der aktuelle Flankenwert modulo 6 verwendet und auf die entsprechende IP umgeschaltet (IPs werden 0
im Uhrzeigersinn nummeriert ). Wenn also die Eingabe war 0
, dann bleibt die IP einfach gleich und wandert langweilig geradeaus hinein !@
. Aber wenn die Eingabe war 1
, dann ist der aktuelle Wert -1
der, der ist 5 (mod 6)
. Also wechseln wir zu der IP, die in derselben Zelle beginnt (dem grünen Pfad). Jetzt #
ist ein No-Op und ?
setzt den Speicherrand auf 0
. )
Inkremente so !
druckt ein 1
. Jetzt schlagen wir noch ~
einmal zu, um das sicherzustellen#
ist immer noch ein No-Op (im Gegensatz dazu, dass wir zu IP 1 wechseln, was das Programm beenden würde). Es ist umwerfend, wie gut in diesem kleinen Programm alles zusammenpasst.
Gruppe 22
Zu beachten ist, dass dies die Gruppe ist, in der sich meine ursprüngliche Lösung befindet. Es handelt sich auch zufällig um die größte Gruppe, da sich das No-Op an zwei verschiedenen Stellen befinden kann und es mehrere Auswahlmöglichkeiten für den tatsächlichen (effektiven No-Op) Befehl gibt.
Gruppe 23
Dies ist die andere Gruppe, die mehrere IPs verwendet. In der Tat verwendet dieser 3 verschiedene IPs. Die obere rechte Ecke ist ein bisschen chaotisch, aber ich werde versuchen, Sie durch Folgendes zu führen:
Also, der Anfang, den Sie schon gesehen haben: <
lenkt den Nordosten ab, ?
liest Eingaben. Jetzt ]
gibt es eine andere Möglichkeit, zwischen IPs zu wechseln: Die Steuerung wechselt im Uhrzeigersinn zur nächsten IP. Also schalten wir die Kontrolle auf den türkisfarbenen Pfad um, der (wie ich weiß, schwer zu erkennen ist) in der nordöstlichen Ecke in südöstlicher Richtung beginnt. Es wird sofort von der reflektiert, <
so dass es sich in die südöstliche Ecke nach Nordwesten wickelt. Es auch trifft das ]
so wir an den Schalter neben IP. Dies ist der graue Pfad, der in der östlichen Ecke beginnt und nach Südwesten führt. Die Eingabe wird gedruckt und dann in die nordöstliche Ecke umgebrochen. <
Leitet den Pfad in die Horizontale um, wo er vom anderen reflektiert wird <
. Jetzt die rechte Hand<
fungiert als Verzweigung: Wenn die Eingabe war 0
, wird die IP nach Nordosten verschoben und in die umbrochen @
. Wenn die Eingabe war 1
, bewegt sich die IP zum !
, springt zum Lef-Thand, <
wo sie reflektiert wird ... jetzt in der Ecke, springt sie zurück zum !
, wird von der Rechten abgelenkt <
, von der Linken reflektiert <
und der Pfad beginnt Über...
Ein ziemliches Durcheinander, aber ein schönes Durcheinander. :)
Mit Timwis erstaunlichem HexagonyColorer erstellte Diagramme .