Narysuj krzywą Hilberta za pomocą ukośników

30

Krzywa Hilberta jest przestrzenią napełniania fraktali, który może być przedstawiony jako systemu Lindenmayer z kolejnych pokoleń, które wyglądają tak:
Krzywa Hilberta
Dzięki http://www.texample.net/tikz/examples/hilbert-curve/ dla obrazu.

Cel

Napisz najkrótszy możliwy program (w bajtach), który pobiera dodatnią liczbę całkowitą n ze standardowego wejścia i rysuje krzywą Hilberta n-tego rzędu do standardowego, używając tylko ukośnika do przodu, ukośnika do tyłu, spacji i nowej linii.

Na przykład, jeśli wejście jest 1wyjściem, musi być

 \
\/

Jeśli wejście jest 2wyjściem, musi być

  /
  \/\
/\   \
 / /\/
 \ \
  \/

Jeśli wejście jest 3wyjściem, musi być

       \
     /\/
    /   /\
    \/\ \ \
  /\  / / /
 / /  \/  \/\
 \ \/\  /\   \
\/   / / / /\/
  /\/ /  \ \
  \   \/\ \/
   \/\   \
     / /\/
     \ \
      \/

I tak dalej. (Wyglądają ładniej, jeśli wkleisz je w coś o mniejszych odstępach między wierszami).

Dane wyjściowe nie powinny zawierać znaków nowej linii powyżej lub poniżej krańców krzywej ani żadnych spacji końcowych na żadnych liniach.

Hobby Calvina
źródło

Odpowiedzi:

10

Rubinowy, 247 230 205 znaków

r=?D
y=d=0
z=(1..2*x=2**gets.to_i.times{r.gsub!(/\w/){$&<?H?'-H~+D~D+~H-':'+D~-H~H-~D+'}}-1).map{' '*2*x}
r.bytes{|c|c>99?(z[y-=s=-~d/2%2][x-=1-d/2]='/\\'[d%2]
x+=d/2
y+=1-s):d-=c
d%=4}
puts z.map &:rstrip

Podejście żółwia ASCII z wykorzystaniem reprezentacji Lindenmayera (spróbuj tutaj ).

Ogromne podziękowania dla @Ventero za trochę golfa.

Howard
źródło
Grałem w golfa jeszcze trochę, mam nadzieję, że nie masz nic przeciwko: ideone.com/kvcPWT - .map(&:rstrip)trzeba było dodać, aby spełnić wymóg „brak spacji końcowych”.
Ventero
@Ventero Dziękujemy. Mam nadzieję, że nie masz nic przeciwko temu, że wybrałem twoje rozwiązanie - możesz nawet odrzucić nawiasy wokół argumentu mapy.
Howard
Ach, oczywiście! Właśnie zdałem sobie sprawę, że można wstawić definicję xi skrócić przypisanie do yi d, w sumie 205 znaków (patrz ten sam link, jak poprzednio).
Ventero
12

Python, 282

from numpy import*
def r(n):
 x=2**n-2;b=3*x/2+1;c=x/2+1;a=zeros((x*2+2,)*2,int);a[x+1,x+1]=1;a[b,x/2]=a[x/2,b]=-1
 if n>1:s=r(n-1);a[:x,c:b]=rot90(s,3)*-1;a[c:b,:x]|=rot90(s)*-1;a[c:b,x+2:]|=s;a[x+2:,c:b]|=s
 return a
for l in r(input()):print''.join(' /\\'[c] for c in l).rstrip()

Wykorzystuje to podejście rekurencyjne do konstruowania krzywej Hilberta n-tego rzędu z poprzedniej krzywej. Krzywe są reprezentowane jako tablica liczb 2d dla lepszego krojenia i manipulacji.

Oto kilka przykładów:

$ python hilbert.py
2
  /
  \/\
/\   \
 / /\/
 \ \
  \/
$ python hilbert.py
3
       \
     /\/
    /   /\
    \/\ \ \
  /\  / / /
 / /  \/  \/\
 \ \/\  /\   \
\/   / / / /\/
  /\/ /  \ \
  \   \/\ \/
   \/\   \
     / /\/
     \ \
      \/
$ python hilbert.py
4
              /
              \/\
            /\   \
           / / /\/
           \ \ \  /\
         /\/  \/  \ \
        /   /\  /\/ /
        \/\ \ \ \   \/\
      /\  / /  \ \/\   \
     / /  \/ /\/   / /\/
     \ \/\  /   /\/ /   /\
   /\/   /  \/\ \   \/\ \ \
  /   /\/ /\  / / /\  / / /
  \/\ \  / /  \/ / /  \/  \/\
/\   \ \ \ \/\   \ \/\  /\   \
 / /\/  \/   / /\/   / / / /\/
 \ \  /\  /\/  \  /\/ /  \ \
  \/  \ \ \  /\/  \   \/\ \/
    /\/ / / /   /\ \/\   \
    \   \/  \/\ \ \  / /\/
     \/\  /\  / / /  \ \
       / / /  \/  \/\ \/
       \ \ \/\  /\   \
        \/   / / / /\/
          /\/ /  \ \
          \   \/\ \/
           \/\   \
             / /\/
             \ \
              \/
grc
źródło
5

Malsys - 234 221 znaków

Czuję tutaj trochę systemów L :) Malsys to internetowy tłumacz systemu L. To nie jest naprawdę poważny wpis, ale czułem, że to rozwiązanie jest dość interesujące.

Składnia Malsys nie jest zbyt dobra do gry w golfa, ponieważ zawiera wiele długich słów kluczowych, ale mimo to jest dość krótka, czytelna i wyrazista.

lsystem HilbertCurveAscii {
    set symbols axiom = R;
    set iterations = 5;
    set rightAngleSlashMode = true;
    interpret F as DrawLine;
    interpret + as TurnLeft;
    interpret - as TurnRight;
    rewrite L to + R F - L F L - F R +;
    rewrite R to - L F + R F R + F L -;
}
process all with HexAsciiRenderer;

http://malsys.cz/g/3DcVFMWn

Tłumacz ustny: http://malsys.cz/Process

Wersja golfowa:

lsystem H{set symbols axiom=R;set iterations=3;set
rightAngleSlashMode=1;interpret.as DrawLine;interpret+as
TurnLeft;interpret-as TurnRight;rewrite L to+R.-L.L-.R+;rewrite
R to-L.+R.R+.L-;}process H with HexAsciiRenderer;

A co powiesz na sześciokątną krzywą Ascii Gosper? :)

      ____
 ____ \__ \
 \__ \__/ / __
 __/ ____ \ \ \
/ __ \__ \ \/
\ \ \__/ / __
 \/ ____ \/ /
    \__ \__/
    __/

http://malsys.cz/g/ae5v5vGB

NightElfik
źródło
2

JavaScript (ES6) 313 340

Edytuj Niektóre postacie usunięte przy użyciu naprawdę złych praktyk - takich jak zmienna globalna w zamiast wartości zwracanej z funkcji H

Konwertując pozycję x, y na odległość d (patrz Wikipedia ) dla każdego x, y i sprawdzając, czy najbliższe pozycje są połączone,

Przetestuj w konsoli FireFox. Wejście przez wyskakujące okienko, wyjście przez konsolę.log.

Nie ma spacji końcowych ani znaków nowej linii powyżej lub poniżej obrazu. Ale każda linia jest zakończona nową linią, myślę, że to właściwy sposób, aby zrobić obraz sztuki Ascii.

n=1<<prompt(),d=n-1
H=(s,x,y)=>{for(w=0;s>>=1;)p=x&s,q=y&s,w+=s*s*(3*!!p^!!q),q||(p&&(x=s-1-x,y=s-1-y),[x,y]=[y,x])}
for(r=t='';++r<d+n;t+='\n')for(r>d?(x=r-d,f=x-1):(f=d-r,x=0),t+=' '.repeat(f),z=r-x;x<=z;)
h=H(n,y=r-x,x)|w,H(n,y,x-1),x?t+=' \\'[h-w<2&w-h<2]:0,H(n,y-1,x++),y?t+=' /'[h-w<2&w-h<2]:0
console.log(t)
edc65
źródło
Możesz zapisać niektóre postacie, używając alertzamiast console.log. Masz również dodatkowe miejsce po forczwartej linii i powinieneś być w stanie pozbyć się ostatniego podziału linii.
Bob
@ Bob tak, w rzeczywistości mogę zapisać jeszcze 15 znaków, zrezygnowałem, widząc, że i tak mam ich ponad 300. Nie lubię używać funkcji „alert”, ponieważ obraz jest całkowicie nierozpoznawalny bez czcionki o stałej wysokości
edc65
2

Perl, 270 znaków

Super golfa

$_=A,%d=<A -BF+AFA+FB- B +AF-BFB-FA+>,$x=2**($n=<>)-2;eval's/A|B/$d{$&}/g;'x$n;s/A|B//g;map{if(/F/){if($r+$p==3){$y+=$p<=>$r}else{$x+=$r<2?$r-$p:$p-$r}$s[($r-1)%4>1?$x--:$x++][$r>1?$y--:$y++]=qw(/ \\)[($p=$r)%2]}else{($r+=2*/-/-1)%=4}}/./g;map{print map{$_||$"}@$_,$/}@s

Nie tyle golfa

$_=A,%d=<A -BF+AFA+FB- B +AF-BFB-FA+>,$x=2**($n=<>)-2;
eval's/A|B/$d{$&}/g;'x$n;
s/A|B//g;
map{if(/F/){
    if($r+$p==3){$y+=$p<=>$r}else{$x+=$r<2?$r-$p:$p-$r}
        $s[($r-1)%4>1?$x--:$x++][$r>1?$y--:$y++]=qw(/ \\)[($p=$r)%2]
    }else{
        ($r+=2*/-/-1)%=4
    }
}/./g;
map{print map{$_||$"}@$_,$/}@s

Mógłbym chyba bardziej pograć w golfa, jeśli lepiej rozumiem Perla. Stosuje podejście systemowe Lindenmayera, stosując reguły produkcji zdefiniowane w wierszu 1.

zabójca
źródło
2

APL (Dyalog Unicode) , 90 bajtów SBCS

⎕∘←¨' +$'r''¨↓1↓∘⍉∘⌽⍣4' /\'[{3|(⊢+⍉)2@(¯1 0+3 1×s÷2)s⊢(¯.5×≢⍵)⊖(2×s←⍴⍵)↑⍵,⍨-⊖⍵}⍣⎕⊢2 2⍴0]

Wypróbuj online!

2 2⍴0 macierz zerowa 2x2

{ }⍣⎕ wprowadź N i zastosuj funkcję N razy

⍵,⍨-⊖⍵ konkatenuje na lewo od matrycy odwróconą pionowo i zanegowaną kopię samej siebie

(2×s←⍴⍵)↑uzupełnij zerami, aby wymiary (zapamiętane jako s) były dwa razy większe niż argumentu

¯.5×≢⍵ obróć w dół, aby wyśrodkować go w pionie, wciśnięty pomiędzy zera wypełnienia

2@(¯1 0+3 1×s÷2) umieść 2-s w określonych lokalizacjach - są to łączniki pomiędzy mniejszymi instancjami fraktala

(⊢+⍉) dodaj macierz z transponowanym ja

3|moduł 3; użyliśmy negacji, więc pamiętaj, że -1≡2 (mod 3) i -2≡1 (mod 3)

' /\'[ ] użyj elementów macierzy jako wskaźników w ciągu ' /\'

1↓∘⍉∘⌽⍣4 przyciąć pusty margines o szerokości 1 elementu ze wszystkich stron

podzielony na linie

' +$'⎕r''¨ usuń końcowe spacje z każdego (wymaga tego wyzwanie)

⎕∘←¨ wyjście każdego

ngn
źródło