Narysuj krzywą Hilberta


12

Krzywa Hilberta jest rodzajem krzywej wypełniającej przestrzeń i zasadniczo odwzorowuje linię na płaszczyznę. Każdy punkt na linii odpowiada tylko jednemu punktowi na płaszczyźnie, a każdy punkt na płaszczyźnie odpowiada tylko jednemu punktowi na linii. Pokazano iteracje od 0 do 4 krzywej Hilberta:

Iteracje 0 do 4:

Cel tego zadania: Napisz kod, który rysuje czwartą iterację krzywej Hilberta, jak zdefiniowano powyżej. Twój kod powinien być kompletny - innymi słowy, jeśli utworzysz funkcję do rysowania krzywej Hilberta, twój kod musi wywołać tę funkcję. Dane wyjściowe można wyświetlić bezpośrednio na ekranie lub zapisać je w pliku obrazu. Krzywa może być obracana lub odwracana, ale linie muszą przecinać się pod kątem prostym, a wynik nie może być rozciągnięty. Sztuka ASCII jest doceniana, ale nie będzie akceptowana. Najkrótszy kod w bajtach wygrywa!


Czy liczba razy to wejście? Czy możemy wybrać dowolną wartość co najmniej 4?
Luis Mendo,

Czy sztukę ASCII uważa się za graficzną?
Gabriel Benamy,

Nie; przepraszam - to byłby duplikat innego pytania
J. Antonio Perez,

@JorgePerez Czy krzywa może mieć inną orientację? Jak twoja wersja przykładów z odwróconą pionowo lub o 90 stopni rotacją
Luis Mendo

Tak! Chociaż ogólny kształt musi być nadal kwadratowy
J. Antonio Perez,

Odpowiedzi:


7

R, 90 bajtów

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")

Bezwstydny port R algorytmu zastosowanego w łączu opublikowanym przez @Luis Mendo.

Dla n=5otrzymujemy:

wprowadź opis zdjęcia tutaj


7

MATL , 39 38 bajtów

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

Pobiera to liczbę iteracji jako dane wejściowe. Jeśli chcesz go na stałe zakodować, zastąp igo numerem.

Program jest portem kodu Matlaba autorstwa Jonasa Lundgrena pokazanego tutaj .

Wynik pokazano poniżej. Możesz także spróbować w MATL Online! Wytworzenie wyjścia zajmuje kilka sekund. Ten kompilator jest eksperymentalny; może być konieczne odświeżenie strony i ponowne naciśnięcie przycisku „Uruchom”, jeśli początkowo nie działa.

wprowadź opis zdjęcia tutaj

Wyjaśnienie

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

Czy możesz wyjaśnić, jak działa Twój kod?
J. Antonio Perez,

Algorytm jest dokładnie taki, jak w łączu. Ale dodam wyjaśnienie
Luis Mendo

@Jorge Explanation dodaje
Luis Mendo

omg, ten, na którym
opierasz swój,

@flawr Wszystkie podziękowania dla Jonasa Lundgrena :-)
Luis Mendo

6

MATLAB, 264 262 161 bajtów

Działa to nadal bardzo podobnie, z tym wyjątkiem, że w zasadzie obliczamy „pochodną” krzywej Hilberta, którą następnie „integrujemy” poprzez „sumę”. Zmniejsza to rozmiar kodu o całkiem sporo bajtów.

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

Stara wersja

To tylko proste podejście rekurencyjne. Dla uproszczenia użyłem liczb zespolonych do przechowywania informacji wektorowych. Możesz zmienić krzywą na części h(0,1,1+i,4). Pierwszy argument p=0to pozycja początkowa, drugi argument fto flaga orientacji ( +1lub -1), trzeci argument dto kierunek / obrót, w którym należy narysować krzywą, a czwarty lto głębokość rekurencji.

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

Tak to wygląda w starszych wersjach:

Tak to wygląda w 2015b:

->

1
W Matlabie R2015b drukuje się w kolorach <3
Luis Mendo

Haha, tak fajnie :)
flawr

@LuisMendo Miałem teraz możliwość gry w golfa dzięki cumsumpomysłowi, który jest po prostu genialny!
flawr

3

MATLAB / Octave, 202 bajty

Zauważyłem, że wersja @LuisMendo, która jest połączona, była znacznie krótsza niż poprzednie „ręcznie robione” rozwiązanie, ale używa zupełnie innego podejścia. Zamieszczam tutaj wersję golfa jako CW:

Ta wersja jest oparta na podejściu systemowym Lindenmayer:

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

wprowadź opis zdjęcia tutaj


3

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

Renderowanie SVG krzywej Hilberta.

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)+'">')

Zaoszczędził 1 bajt dzięki Neilowi


1
Spróbujfill=none
Neil,

2

Python 3, 177 175 171 bajtów

Prosta implementacja systemu Lindenmayera dla krzywej Hilberta. Zapraszamy do gry w golfa!

Edycja: -2 bajty dzięki Kade. -3 bajty od zmiany struktury budowy krzywej Hilberta. -1 bajt dzięki produktom ETH.

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)

wprowadź opis zdjęcia tutaj

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)

Zmiana sposobu tworzyć tmożna zapisać dwa bajty: t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Ponieważ wzór jest prawie taki sam dla nich dwóch, zastanawiam się, czy jest jakiś sposób, aby tego użyć ...
Kade

Być może zmienić, if c>"E":aby if"E"<c:zapisać bajt?
ETHproductions

1

MSWLogo (wersja 6.5b), 136 bajtów

Na podstawie końcowego programu krzywej Hilberta tutaj .

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

hZdefiniowana jest funkcja , która przyjmuje liczbę iteracji :n(na podstawie 1), kąt :a, długość :l. Jest rekurencyjny, nazywając siebie niższą iteracją z :azanegowanym kątem w dwóch przypadkach, aby uzyskać prawidłową orientację.

  • rt :a, lt :aobróć żółwia (trójkąt, którego ścieżka jest wytyczona) w prawo, w lewo o :astopnie.
  • fd :lprzesuwa żółwia krok po :lkroku.

Wreszcie, funkcja nazywa się: h 5 90 9. Żółw może być ukryte za dodatkowe 2 bajtach ht.

(5-1) -ta iteracja


Co się dzieje w lewym górnym rogu?
flawr

@flawr To żółw. Można to ukryć, dołączając ht.
dla Moniki

1

Mathematica 128 bajtów

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]]

Jeśli chcesz, zamień 4 powyżej na inną liczbę iteracji.

Wykonano jako system Lindenmayera z sekwencjami liczb całkowitych zamiast ciągów znaków, więc druga reguła produkcyjna jest tylko przeczeniem pierwszej reguły. Ta wersja ma 151 bajtów.

Port kodu MATLAB Jonasa Lundgrena ma tylko 128 bajtów.

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]

Widzę, że w przyszłej wersji Mathematica może to być naprawdę krótkie, coś w rodzaju:

Graphics@HilbertCurve[n]

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


1

LindenMASM , 63 bajtów

Kolejne pytanie z odpowiedzią LindenMASM? Niesamowite!

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

Ponownie, z powodu niektórych błędów rysowania w Pythonie turtle, czasami po uruchomieniu tego całego rysunku nie ma. Jak jednak widać, faktycznie działa:

4. iteracja

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.