Desenhe a curva de Hilbert

12

Uma curva de Hilbert é um tipo de curva de preenchimento de espaço e basicamente mapeia uma linha para um plano. Cada ponto na linha corresponde a apenas um ponto no plano e cada ponto no plano corresponde a apenas um ponto na linha. São mostradas as iterações de 0 a 4 da Curva de Hilbert:

Iterações de 0 a 4:

O objetivo desta tarefa: Escreva um código que desenhe a quarta iteração da Curva de Hilbert, conforme definido acima. Seu código deve estar completo - em outras palavras, se você criar uma função para desenhar a Curva de Hilbert, seu código deverá chamar essa função. A saída pode ser exibida diretamente na tela ou você pode gravar a saída em um arquivo de imagem. A curva pode ser girada ou invertida, mas as linhas devem se cruzar em ângulos retos e a saída não pode ser esticada. A arte ASCII é apreciada, mas não será aceita. O menor código em bytes vence!

J. Antonio Perez
fonte
É o número de vezes que uma entrada? Ou podemos escolher qualquer valor pelo menos 4?
Luis Mendo
A arte ASCII é considerada gráfica?
Gabriel Benamy
Não; desculpe -, então seria uma duplicata de outra pergunta
J. Antonio Perez
@JorgePerez A curva pode ter uma orientação diferente? Como uma versão vertical capotou ou 90 graus de rotação de seus exemplos
Luis Mendo
Sim! Embora a forma obrigatória geral ainda ser quadrado
J. Antonio Perez

Respostas:

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

Porta R descarada do algoritmo usado no link postado por @Luis Mendo.

Pois n=5temos:

insira a descrição da imagem aqui

Billywob
fonte
7

MATL , 39 38 bytes

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

Isso leva o número de iterações como entrada. Se você deseja codificá-lo, substitua ipelo número.

O programa é uma porta do código Matlab de Jonas Lundgren mostrada aqui .

O resultado é apresentado abaixo. Você também pode experimentá-lo no MATL Online! Demora alguns segundos para produzir a saída. Este compilador é experimental; pode ser necessário atualizar a página e pressionar "Executar" novamente se não funcionar inicialmente.

insira a descrição da imagem aqui

Explicação

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
fonte
Você poderia explicar como seu código funciona?
J. Antonio Perez
O algoritmo é exatamente como no link. Mas vou acrescentar uma explicação
Luis Mendo
@Jorge Explicação adicionada
Luis Mendo
omg, aquele em que você baseou o seu é muito mais fácil que o meu = /
flawr
@flawr Todo o crédito para Jonas Lundgren :-)
Luis Mendo
6

Matlab, 264 262 161 bytes

Isso ainda funciona da mesma forma, exceto que basicamente calculamos a "derivada" da curva de hilbert, que então "integramos" via `cumsum``. Isso reduz o tamanho do código em vários 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

Versão antiga

Esta é apenas uma abordagem recursiva simples. Usei números complexos para armazenar informações vetoriais por simplicidade. Você pode alterar a curva na peça h(0,1,1+i,4). O primeiro argumento p=0é a posição inicial, o segundo argumento fé uma bandeira para a orientação ( +1ou -1), o terceiro argumento dé a direção / rotação na qual a curva deve ser desenhada e o quarto lé a profundidade da recursão.

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

Isto é o que parece nas versões mais antigas:

É assim que é em 2015b:

->
flawr
fonte
1
No Matlab R2015b, plota em cores <3
Luis Mendo
Haha tão legal :)
flawr
@LuisMendo Agora eu era capaz de jogar um pouco com a cumsumidéia que é simplesmente brilhante!
flawr
3

MATLAB / oitava, 202 bytes

Percebi que a versão vinculada ao @LuisMendo é muito mais curta que a solução "handmade" anterior , mas usa uma abordagem totalmente diferente. Estou postando uma versão golfada aqui agora como CW:

Esta versão é baseada na abordagem do sistema 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

insira a descrição da imagem aqui

flawr
fonte
3

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

Uma renderização SVG da Curva de Hilbert.

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

Guardado 1 byte graças a Neil

Arnauld
fonte
1
Tentefill=none
Neil
2

Python 3, 177 175 171 bytes

Uma implementação simples do sistema Lindenmayer para a curva de Hilbert. Sugestões de golfe são bem-vindas!

Edit: -2 bytes graças ao Kade. -3 bytes da reestruturação de como a curva de Hilbert é construída. -1 byte com agradecimentos a 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)

insira a descrição da imagem aqui

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
fonte
Alterar como você forma tpode salvar dois bytes: t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Desde o padrão é quase o mesmo para os dois Eu quero saber se há alguma maneira de usar isso ..
Kade
Talvez mude if c>"E":para if"E"<c:salvar um byte?
ETHproductions
1

MSWLogo (Versão 6.5b), 136 bytes

Com base no programa final da curva de Hilbert aqui .

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

hÉ definida uma função , que leva o número de iterações :n(com base em 1), ângulo :a, comprimento :l. É recursivo, chamando uma iteração mais baixa de si mesmo com o ângulo :anegado em duas instâncias para obter a orientação correta.

  • rt :a, lt :agire a tartaruga (triângulo cujo caminho é traçado) para a direita, deixada em :agraus.
  • fd :lmove a tartaruga para a frente em :letapas.

Finalmente, a função é chamada: h 5 90 9. A tartaruga pode ser escondida por 2 bytes extras ht,.

(5-1) -a iteração

para Monica
fonte
O que está acontecendo no canto superior esquerdo?
flawr
@ Flawr Essa é a tartaruga. Pode ser oculto anexando ht.
para Monica
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]]

Substitua os 4 acima por um número diferente de iterações, se desejar.

Feito como um sistema Lindenmayer com seqüências inteiras em vez de sequências de strings, a segunda regra de produção é apenas a negativa da primeira regra. Esta versão tem 151 bytes.

A porta do código MATLAB de Jonas Lundgren é de apenas 128 bytes.

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]

Vejo que em uma versão futura do Mathematica, isso pode se tornar muito curto, algo como:

Graphics@HilbertCurve[n]

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

Kelly Lowder
fonte
1

LindenMASM , 63 bytes

Outra pergunta com uma resposta LindenMASM? Impressionante!

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

Mais uma vez, devido a alguns erros de desenho do Python turtle, às vezes quando você executa isso, o desenho inteiro não está lá. No entanto, você pode ver que ele realmente funciona:

4ª iteração

Kade
fonte