Befunge, 444 368 323 Bytes
&1>\1-:v
0v^*2\<_$00p>
_>:10p\:20pv^_@#-*2g00:+1,+55$
^!-<v*2g000<>$#<0>>-\:v
g2*^>>10g20g+v \ ^*84g_$:88+g,89+g,\1+:00
v#*!-1g02!g01_4^2_
>::00g2*-!\1-:10g-\20g-++>v
87+#^\#p01#<<v!`g01/2\+76:_
vv1-^#1-g01:\_$:2/20g`!
_ 2/^>:10g#vv#`g02/4*3:\+77
v>0p^^/2:/2_
<^2-1-g02</2`#*3:
0g+10p2*:^*3_1
! "#%$
%$"#!
!!##%
|||_
_ __
Probieren Sie es online!
Der typische Ansatz zum Zeichnen der Hilbert-Kurve besteht darin, dem Pfad als Folge von Strichen und Kurven zu folgen, das Ergebnis in eine Bitmap oder einen Speicherbereich zu rendern und dieses Rendern dann auszuschreiben, wenn der Pfad vollständig ist. Dies ist in Befunge einfach nicht möglich, wenn nur 2000 Byte Arbeitsspeicher zur Verfügung stehen und dies auch die Quelle des Programms selbst einschließt.
Wir haben uns hier also eine Formel ausgedacht, die genau angibt, welches Zeichen für eine bestimmte x, y-Koordinate ausgegeben werden soll. Um zu verstehen , wie dies funktioniert, ist es am einfachsten , das ASCII - Rendering zu ignorieren , mit zu beginnen, und man denke nur an der Kurve als Kasten Zeichen aus: ┌
, ┐
, └
, ┘
, │
, und ─
.
Wenn wir die Kurve so betrachten, können wir sofort erkennen, dass die rechte Seite ein exakter Spiegel der linken Seite ist. Die Zeichen auf der rechten Seite können einfach bestimmt werden, indem der Partner auf der linken Seite nachgeschlagen und horizontal reflektiert wird (dh das Auftreten von ┌
und ┐
wird wie └
und vertauscht ┘
).
Wenn wir dann die untere linke Ecke betrachten, können wir wieder sehen, dass die untere Hälfte eine Reflexion der oberen Hälfte ist. So werden die Zeichen auf der Unterseite einfach dadurch bestimmt, dass ihr Partner oben nachgeschlagen und vertikal reflektiert wird (dh Vorkommen von ┌
und └
werden vertauscht, so wie ┐
und ┘
).
Die verbleibende Hälfte dieser Ecke ist etwas weniger auffällig. Der rechte Block kann aus einer vertikalen Reflexion des diagonal angrenzenden Blocks abgeleitet werden.
Der linke Block kann aus einer vertikalen Reflexion des Blocks ganz links oben in der vollständigen Kurve abgeleitet werden.
An diesem Punkt bleibt uns nur die obere linke Ecke, die nur eine weitere Hilbert-Kurve ist, die eine Iteration tiefer liegt. Theoretisch sollten wir den Vorgang jetzt nur noch einmal wiederholen müssen, aber es gibt einen kleinen Haken - auf dieser Ebene sind die linke und die rechte Hälfte des Blocks keine exakten Spiegel voneinander.
Auf allen anderen Ebenen als der obersten Ebene müssen die Zeichen in der unteren Ecke als Sonderfall behandelt werden, in dem das ┌
Zeichen als ─
und das │
Zeichen als reflektiert wird └
.
Davon abgesehen können wir diesen Vorgang wirklich nur rekursiv wiederholen. Auf der letzten Ebene wird das Zeichen oben links als ┌
und das Zeichen darunter als fest codiert │
.
Nachdem wir nun die Form der Kurve an einer bestimmten x, y-Koordinate bestimmen können, wie übersetzen wir das in das ASCII-Rendering? Es ist eigentlich nur eine einfache Zuordnung, die jede mögliche Kachel in zwei ASCII-Zeichen übersetzt.
┌
wird _
(Leerzeichen plus Unterstrich)
┐
wird
(zwei Leerzeichen)
└
wird |_
(senkrechter Strich plus Unterstrich)
┘
wird |
(senkrechter Strich plus Leerzeichen)
│
wird |
(wieder ein vertikaler Strich plus Leerzeichen)
─
wird __
(zwei Unterstriche)
Dieses Mapping ist zunächst nicht intuitiv, aber Sie können sehen, wie es funktioniert, wenn Sie zwei entsprechende Renderings nebeneinander betrachten.
Und das ist im Grunde alles, was dazu gehört. Eigentlich ist die Implementierung dieses Algorithmus in Befunge ein weiteres Problem, aber ich werde diese Erklärung für ein anderes Mal belassen.