Dibuja la curva de Hilbert

12

Una curva de Hilbert es un tipo de curva de relleno de espacio, y básicamente asigna una línea a un plano. Cada punto en la línea corresponde a solo un punto en el plano, y cada punto en el plano corresponde a solo un punto en la línea. Se muestran las iteraciones 0 a 4 de la curva de Hilbert:

Iteraciones 0 hasta 4:

El objetivo de esta tarea: escribir código que dibuje la cuarta iteración de la curva de Hilbert, como se definió anteriormente. Su código debe estar completo; en otras palabras, si crea una función para dibujar la curva de Hilbert, su código debe llamar a esa función. El resultado puede mostrarse directamente en la pantalla o puede escribir el resultado en un archivo de imagen. La curva puede girarse o voltearse, pero las líneas deben cruzarse en ángulo recto y la salida no se puede estirar. El arte ASCII es apreciado pero no será aceptado. ¡El código más corto en bytes gana!

J. Antonio Perez
fuente
¿Es el número de veces una entrada? ¿O podemos elegir cualquier valor al menos 4?
Luis Mendo
¿El arte ASCII se considera gráfico?
Gabriel Benamy
No; lo siento - entonces sería un duplicado de otra pregunta
J. Antonio Perez
@JorgePerez ¿Puede la curva tener una orientación diferente? Como una versión volteada verticalmente o girada a 90 grados de sus ejemplos
Luis Mendo el
¡Si! Aunque la forma general todavía debe ser cuadrada
J. Antonio Pérez

Respuestas:

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

Puerto R descarado del algoritmo utilizado en el enlace publicado por @Luis Mendo.

Porque n=5obtenemos:

ingrese la descripción de la imagen aquí

Billywob
fuente
7

MATL , 39 38 bytes

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

Esto toma el número de iteraciones como entrada. Si desea codificarlo, reemplácelo ipor el número.

El programa es un puerto del código Matlab de Jonas Lundgren que se muestra aquí .

El resultado se muestra a continuación. ¡También puedes probarlo en MATL Online! Se tarda unos segundos en producir la salida. Este compilador es experimental; es posible que deba actualizar la página y presionar "Ejecutar" nuevamente si no funciona inicialmente.

ingrese la descripción de la imagen aquí

Explicación

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
fuente
¿Podría explicar cómo funciona su código?
J. Antonio Perez
El algoritmo es exactamente como en el enlace. Pero agregaré una explicación
Luis Mendo el
@Jorge Explicación agregada
Luis Mendo
Dios mío, aquel en el que
basaste el
@flawr Todo el crédito a Jonas Lundgren :-)
Luis Mendo el
6

MATLAB, 264 262 161 bytes

Esto funciona igual, excepto que básicamente calculamos la "derivada" de la curva de hilbert, que luego "integramos" a través de `cumsum``. Esto reduce el tamaño del código en muchos 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

Versión antigua

Este es solo un enfoque recursivo simple. Usé números complejos para almacenar información vectorial para simplificar. Puede cambiar la curva en la parte h(0,1,1+i,4). El primer argumento p=0es la posición inicial, el segundo argumento fes una bandera para la orientación ( +1o -1), el tercer argumento des la dirección / rotación en la que se debe dibujar la curva y el cuarto les la profundidad de recursión.

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

Así es como se ve en las versiones anteriores:

Así es como se ve en 2015b:

->
falla
fuente
1
En Matlab R2015b traza en colores <3
Luis Mendo
Jaja tan genial :)
flawr
@LuisMendo ¡Ahora pude jugar un poco al golf con la cumsumidea que es genial!
falla
3

MATLAB / Octave, 202 bytes

Noté que la versión @LuisMendo vinculada es mucho más corta que la solución "hecha a mano" anterior, pero utiliza un enfoque completamente diferente. Estoy publicando una versión de golf aquí ahora como CW:

Esta versión se basa en el enfoque del 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

ingrese la descripción de la imagen aquí

error
fuente
3

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

Una representación SVG de la 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 gracias a Neil

Arnauld
fuente
1
Pruebafill=none
Neil
2

Python 3, 177 175 171 bytes

Una implementación simple del sistema Lindenmayer para la curva de Hilbert. Sugerencias de golf bienvenidas!

Editar: -2 bytes gracias a Kade. -3 bytes desde la reestructuración de cómo se construye la curva de Hilbert. -1 byte con agradecimiento 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)

ingrese la descripción de la imagen aquí

No golfista

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
fuente
Cambiar la forma usted forma tpuede ahorrar dos bytes: t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Dado que el patrón es casi el mismo para los dos, me pregunto si hay alguna forma de usar eso ...
Kade
¿Quizás cambiar if c>"E":a if"E"<c:para guardar un byte?
ETHproductions
1

MSWLogo (Versión 6.5b), 136 bytes

Basado en el programa final de la curva de Hilbert aquí .

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

Se hdefine una función , que toma varias iteraciones :n(basadas en 1), ángulo :a, longitud :l. Es recursivo, llamando a una iteración más baja de sí mismo con el ángulo :anegado en dos casos para obtener la orientación correcta.

  • rt :a, lt :agire la tortuga (cosita triangular cuyo camino se traza) derecha, izquierda en :agrados.
  • fd :lmueve la tortuga hacia adelante por :lpasos.

Por último, la función se llama: h 5 90 9. La tortuga puede estar oculto por un extra de 2 bytes, ht.

(5-1) -th iteración

para Monica
fuente
¿Qué está pasando en la esquina superior izquierda?
falla
@flawr Esa es la tortuga. Se puede ocultar agregando ht.
para Mónica el
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]]

Reemplace los 4 anteriores con un número diferente de iteraciones si lo desea.

Hecho como un sistema Lindenmayer con secuencias enteras en lugar de secuencias de cadenas, por lo que la segunda regla de producción es solo lo negativo de la primera regla. Esta versión es de 151 bytes.

El puerto del código MATLAB de Jonas Lundgren es de solo 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]

Veo que en una versión futura de Mathematica, esto puede ser realmente corto, algo así como:

Graphics@HilbertCurve[n]

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

Kelly Lowder
fuente
1

LindenMASM , 63 Bytes

¿Otra pregunta con una respuesta LindenMASM? ¡Increíble!

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

Una vez más, debido a algunos errores de dibujo con Python turtle, a veces, cuando ejecuta esto, todo el dibujo no está allí. Sin embargo, puede ver que realmente funciona:

4ta iteración

Kade
fuente