Zeichnen Sie die Hilbert-Kurve

12

Eine Hilbert-Kurve ist eine Art raumfüllende Kurve und ordnet im Grunde eine Linie einer Ebene zu. Jeder Punkt in der Linie entspricht nur einem Punkt in der Ebene, und jeder Punkt in der Ebene entspricht nur einem Punkt auf der Linie. Dargestellt sind die Iterationen 0 bis 4 der Hilbert-Kurve:

Iterationen 0 bis 4:

Das Ziel dieser Aufgabe: Schreiben Sie Code, der die vierte Iteration der Hilbert-Kurve wie oben definiert zeichnet. Ihr Code sollte vollständig sein. Wenn Sie also eine Funktion zum Zeichnen der Hilbert-Kurve erstellen, muss Ihr Code diese Funktion aufrufen. Die Ausgabe kann entweder direkt auf dem Bildschirm angezeigt werden, oder Sie können die Ausgabe in eine Bilddatei schreiben. Die Kurve kann gedreht oder gespiegelt werden, die Linien müssen sich jedoch im rechten Winkel schneiden, und die Ausgabe kann nicht gedehnt werden. ASCII-Kunst wird geschätzt, aber nicht akzeptiert. Kürzester Code in Bytes gewinnt!

J. Antonio Perez
quelle
Ist die Anzahl der Eingaben? Oder können wir einen Wert von mindestens 4 wählen?
Luis Mendo
Wird ASCII-Kunst als grafisch angesehen?
Gabriel Benamy
Nein; Entschuldigung - dann wäre es ein Duplikat einer anderen Frage
J. Antonio Perez
@JorgePerez Kann die Kurve eine andere Ausrichtung haben? Wie eine vertikal gedrehte oder um 90 Grad gedrehte Version Ihrer Beispiele
Luis Mendo
Ja! Obwohl die Gesamtform immer noch quadratisch sein muss
J. Antonio Perez

Antworten:

7

R, 90 Bytes

n=scan();a=1+1i;b=1-1i;z=0;for(k in 1:n)z=c((w<-1i*Conj(z))-a,z-b,z+a,b-w)/2;plot(z,t="s")

Schamloser R-Port des Algorithmus, der in dem von @Luis Mendo geposteten Link verwendet wird.

Denn n=5wir bekommen:

Bildbeschreibung hier eingeben

Billywob
quelle
7

MATL , 39 38 Bytes

O5:"tZjJ*JQ-wJq+t2+&y2j+_v2/]XG25Y01ZG

Dies übernimmt die Anzahl der Iterationen als Eingabe. Wenn Sie es hart codieren möchten, ersetzen Sie es idurch die Nummer.

Das Programm ist eine Portierung des hier gezeigten Matlab-Codes von Jonas Lundgren .

Das Ergebnis ist unten dargestellt. Sie können es auch bei MATL Online ausprobieren! Die Ausgabe dauert einige Sekunden. Dieser Compiler ist experimentell. Möglicherweise müssen Sie die Seite aktualisieren und erneut auf "Ausführen" klicken, wenn dies anfangs nicht funktioniert.

Bildbeschreibung hier eingeben

Erläuterung

O          % Push 0. This is the initial value of "z" in the original code
5:"        % Do 5 times
  t        %   Duplicate
  Zj       %   Complex conjugate
  J*       %   Multiply by 1j (imaginary unit). This is "w" in the original code
  JQ-      %   Subtract 1+1j
  w        %   Swap: brings copy of "z" to top
  Jq+      %   Add 1-1j
  t        %   Duplicate
  2+       %   Add 2
  &y       %   Duplicate the third element from top
  2j+_     %   Add 2j and negate
  v        %   Concatenate the three matrices vertically
  2/       %   Divide by 2
]          % End
XG         % Plot (in complex plane). The numbers are joined by straight lines
25Y0       % Push string 'square'
1ZG        % Make axis square
Luis Mendo
quelle
Können Sie erklären, wie Ihr Code funktioniert?
J. Antonio Perez
Der Algorithmus ist genau wie im Link. Aber ich werde eine Erklärung hinzufügen
Luis Mendo
@Jorge Erklärung hinzugefügt
Luis Mendo
omg, das, auf dem du basiert hast, ist so viel einfacher als meins = /
flawr 18.11.16
@flawr All credit to Jonas Lundgren :-)
Luis Mendo
6

MATLAB, 264 262 161 Bytes

Dies funktioniert immer noch sehr ähnlich, außer dass wir im Grunde genommen die "Ableitung" der Hilbert-Kurve berechnen, die wir dann über "Cumsum" "integrieren". Dies reduziert die Codegröße um eine ganze Menge Bytes.

function c;plot(cumsum([0,h(1,1+i,4)]));axis equal;end function v=h(f,d,l);v=d*[i*f,1,-i*f];if l;l=l-1;D=i*d*f;w=h(f,d,l);x=h(-f,D,l);v=[x,D,w,d,w,-D,-x];end;end

Alte Version

Dies ist nur ein rekursiver Ansatz. Ich habe der Einfachheit halber komplexe Zahlen verwendet, um vektorielle Informationen zu speichern. Sie können die Kurve am Teil ändern h(0,1,1+i,4). Das erste Argument p=0ist die Anfangsposition, das zweite Argument fist ein Flag für die Ausrichtung ( +1oder -1), das dritte Argument dist die Richtung / Drehung, in der die Kurve gezeichnet werden soll, und das vierte Argument list die Rekursionstiefe.

function c;hold on;h(0,1,1+i,4);axis equal;end function p=h(p,f,d,l);q=@plot;if l;l=l-1;d=i*d*f;p=h(p,-f,d,l);q(p+[0,d]);p=p+d;d=-i*d*f;p=h(p,f,d,l);q(p+[0,d]);p=p+d;p=h(p,f,d,l);d=-i*d*f;q(p+[0,d]);p=p+d;p=h(p,-f,d,l);else;q(p + d*[0,i*f,1+i*f,1]);p=p+d;end;end

So sieht es in älteren Versionen aus:

So sieht es 2015b aus:

->
Fehler
quelle
1
In Matlab R2015b werden Diagramme in Farben <3 erstellt
Luis Mendo
Haha so cool :)
Fehler
@LuisMendo Ich konnte jetzt mit der cumsumIdee, die einfach genial ist, ein bisschen Golf spielen !
Fehler
3

MATLAB / Octave, 202 Bytes

Ich bemerkte die Version @LuisMendo verknüpft heißt war viel kürzer als die bisherigen „handmade“ Lösung nutzt aber einen ganz anderen Ansatz. Ich poste hier jetzt eine Golfversion als CW:

Diese Version basiert auf dem Lindenmayer-Systemansatz:

A=zeros(0,2);B=A;C=A;D=A;n=[0,1];e=[1,0];for k=1:4;a=[B;n;A;e;A;-n;C];b=[A;e;B;n;B;-e;D];c=[D;-e;C;-n;C;e;A];D=[C;-n;D;-e;D;n;B];A=a;B=b;C=c;end;A=[0,0;cumsum(A)];plot(A(:,1),A(:,2));axis off;axis equal

Bildbeschreibung hier eingeben

fehlerhaft
quelle
3

JavaScript (ES6), 266 ... 233 232 Bytes

Ein SVG-Rendering der Hilbert-Kurve.

document.write('<svg><path fill=none stroke=red d="M8 8'+(f=(i,s='2',d=x=y=8)=>i?f(i-1,s.replace(/./g,c=>[32410401423,,10432423401][+c]||c)):s.replace(/./g,c=>c-4?(d+=c&1&&c-2,''):`L${x+=4-'4840'[d&=3]} ${y+=4-'0484'[d]}`))(5)+'">')

1 Byte dank Neil gespeichert

Arnauld
quelle
1
Versuchen Siefill=none
Neil
2

Python 3, 177 175 171 Bytes

Eine einfache Implementierung des Lindenmayer-Systems für die Hilbert-Kurve. Golfvorschläge willkommen!

Edit: -2 Bytes dank Kade. -3 Bytes aus der Umstrukturierung der Hilbert-Kurve. -1 Byte mit Dank an ETHproductions.

from turtle import*;s="a";exec('t=""\nfor c in s:t+=c>"F"and"+-abFF-+baFFba-+FFab+-"[c<"b"::2]or c\ns=t;'*5)
for c in s:
 if"-">c:rt(90)
 elif"F">c:lt(90)
 elif"a">c:fd(9)

Bildbeschreibung hier eingeben

Ungolfing

import turtle

hilbert_seq = "a"

for _ in range(5):
    new_seq = ""
    for char in hilbert_seq:
        if char == "a":
            new_seq += "-bF+aFa+Fb-"
        elif char == "b":
            new_seq += "+aF-bFb-Fa+"
        else:
            new_seq += char
    hilbert_seq = new_seq

for char in hilbert_seq:
    if char == "F":
        turtle.forward(9)
    elif char == "+":
        turtle.right(90)
    elif char == "-":
        turtle.left(90)
Sherlock9
quelle
Ändern , wie Sie bilden tzwei Bytes speichern können: t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Da das Muster für die beiden fast gleich ist, frage ich mich, ob es eine Möglichkeit gibt, das zu verwenden.
Kade
Vielleicht ändern if c>"E":, if"E"<c:um ein Byte zu speichern?
ETHproductions
1

MSWLogo (Version 6.5b), 136 Byte

Basierend auf dem endgültigen Hilbert-Kurvenprogramm hier .

to h :n :a :l
if :n=0[stop]
rt :a
h :n-1(-:a):l
fd :l
lt :a
h :n-1 :a :l
fd :l
h :n-1 :a :l
lt :a
fd :l
h :n-1(-:a):l
rt :a
end
h 5 90 9

Es hwird eine Funktion definiert, die die Anzahl der Iterationen :n(1-basiert), den Winkel :aund die Länge verwendet :l. Es ist rekursiv und ruft eine niedrigere Iteration von sich selbst auf, wobei der Winkel :ain zwei Fällen negiert wird, um die richtige Ausrichtung zu erzielen.

  • rt :a, lt :adrehe die Schildkröte (Dreieck-Ding, dessen Weg verfolgt wird) nach rechts, links von:a Grad.
  • fd :lbewegt die Schildkröte schrittweise vorwärts :l.

Schließlich wird die Funktion aufgerufen: h 5 90 9. Die Schildkröte kann für zusätzliche 2 Bytes ausgeblendet werden ht.

(5-1) -te Iteration

u54112
quelle
Was ist los in der oberen linken Ecke?
Fehler
@flawr Das ist die Schildkröte. Es kann durch Anhängen ausgeblendet werden ht.
u54112
1

Mathematica 128 Bytes

Graphics[Line@AnglePath[Total/@Split[Cases[Nest[#/.{-2->(s=##&@@#&)[l={-1,2,0,1,-2,0,-2,1,0,2,-1}],2->s@-l}&,{-2},4],-1|1|0],#!=0&][[;;-2,;;-2]]*Pi/2]]

Ersetzen Sie die 4 oben durch eine andere Anzahl von Iterationen, wenn Sie möchten.

Wird als Lindenmayer-System mit ganzzahligen Sequenzen anstelle von Zeichenfolgen ausgeführt, sodass die zweite Produktionsregel nur das Negativ der ersten Regel ist. Diese Version ist 151 Bytes.

Der Port des MATLAB-Codes von Jonas Lundgren ist nur 128 Byte groß.

z=0;Graphics[Line[{Re[#],Im[#]}&/@Flatten[Table[w=I*Conjugate[z];z={w-(a=1+I),z-(b=1-I),z+a,b-w}/2,{k,5}][[5]]]],AspectRatio->1]

Ich sehe, dass dies in einer zukünftigen Version von Mathematica sehr kurz werden kann, so etwas wie:

Graphics@HilbertCurve[n]

http://mathworld.wolfram.com/HilbertCurve.html

Kelly Lowder
quelle
1

LindenMASM , 63 Bytes

Noch eine Frage mit einer LindenMASM-Antwort? Genial!

STT
AXI A
INC 5
SET F 0
RPL A -BF+AFA+FB-
RPL B +AF-BFB-FA+
END

Aufgrund einiger Zeichnungsfehler mit Python ist turtlemanchmal, wenn Sie dies ausführen, die gesamte Zeichnung nicht vorhanden. Sie können jedoch sehen, dass es tatsächlich funktioniert:

4. Iteration

Kade
quelle