Dessinez la courbe de Hilbert

12

Une courbe de Hilbert est un type de courbe de remplissage d'espace, et elle mappe essentiellement une ligne à un plan. Chaque point de la ligne correspond à un seul point du plan et chaque point du plan correspond à un seul point de la ligne. Les itérations 0 à 4 de la courbe de Hilbert sont illustrées:

Itérations de 0 à 4:

L'objectif de cette tâche: écrire du code qui dessine la quatrième itération de la courbe de Hilbert, comme défini ci-dessus. Votre code doit être complet - en d'autres termes, si vous créez une fonction pour dessiner la courbe de Hilbert, votre code doit appeler cette fonction. La sortie peut être affichée directement sur l'écran ou vous pouvez écrire la sortie dans un fichier image. La courbe peut être tournée ou inversée, mais les lignes doivent se croiser à angle droit et la sortie ne peut pas être étirée. L'art ASCII est apprécié mais ne sera pas accepté. Le code le plus court en octets gagne!

J. Antonio Perez
la source
Le nombre de fois est-il une entrée? Ou pouvons-nous choisir n'importe quelle valeur au moins 4?
Luis Mendo
L'art ASCII est-il considéré comme graphique?
Gabriel Benamy
Non; désolé - alors ce serait un double d'une autre question
J. Antonio Perez
@JorgePerez La courbe peut-elle avoir une orientation différente? Comme une version à retournement vertical ou à 90 degrés de vos exemples
Luis Mendo
Oui! Bien que la forme générale doive toujours être carrée
J. Antonio Perez

Réponses:

7

R, 90 octets

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

Port R sans vergogne de l'algorithme utilisé dans le lien publié par @Luis Mendo.

Car n=5nous obtenons:

entrez la description de l'image ici

Billywob
la source
7

MATL , 39 38 octets

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

Cela prend le nombre d'itérations en entrée. Si vous souhaitez le coder en dur, remplacez-le ipar le numéro.

Le programme est un portage du code Matlab de Jonas Lundgren montré ici .

Le résultat est illustré ci-dessous. Vous pouvez également l'essayer sur MATL Online! Il faut quelques secondes pour produire la sortie. Ce compilateur est expérimental; vous devrez peut-être actualiser la page et appuyer à nouveau sur "Exécuter" si cela ne fonctionne pas initialement.

entrez la description de l'image ici

Explication

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
la source
Pourriez-vous expliquer comment fonctionne votre code?
J.Antonio Perez
L'algorithme est exactement comme dans le lien. Mais j'ajouterai une explication
Luis Mendo
@Jorge Explanation ajouté
Luis Mendo
omg, celui dont vous avez basé le vôtre est tellement plus facile que le mien = /
flawr
@flawr Tous les crédits à Jonas Lundgren :-)
Luis Mendo
6

MATLAB, 264 262 161 octets

Cela fonctionne toujours de la même façon, sauf que nous calculons essentiellement la "dérivée" de la courbe de hilbert, que nous "intégrons" ensuite via `cumsum '. Cela réduit la taille du code par un tas d'octets.

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

Ancienne version

Il s'agit simplement d'une approche récursive simple. J'ai utilisé des nombres complexes pour stocker des informations vectorielles pour plus de simplicité. Vous pouvez modifier la courbe de la pièce h(0,1,1+i,4). Le premier argument p=0est la position initiale, le deuxième argument fest un indicateur pour l'orientation ( +1ou -1), le troisième argument dest la direction / rotation dans laquelle la courbe doit être tracée et le quatrième lest la profondeur de récursivité.

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

Voici à quoi cela ressemble dans les anciennes versions:

Voici à quoi cela ressemble en 2015b:

->
flawr
la source
1
Dans Matlab R2015b, il trace des couleurs <3
Luis Mendo
Haha so cool :)
flawr
@LuisMendo J'ai maintenant pu jouer un peu au golf avec l' cumsumidée qui est tout simplement géniale!
flawr
3

MATLAB / Octave, 202 octets

J'ai remarqué la la version @LuisMendo liées est - était beaucoup plus courte que les précédentes solution « fait main » mais utilise une approche tout à fait différente. Je poste une version golfée ici maintenant en tant que CW:

Cette version est basée sur l'approche système 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

entrez la description de l'image ici

défauts
la source
3

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

Un rendu SVG de la courbe 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)+'">')

1 octet enregistré grâce à Neil

Arnauld
la source
1
Essayezfill=none
Neil
2

Python 3, 177 175 171 octets

Une implémentation simple du système Lindenmayer pour la courbe de Hilbert. Suggestions de golf bienvenues!

Edit: -2 octets grâce à Kade. -3 octets issus de la restructuration de la construction de la courbe de Hilbert. -1 octet avec merci à 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)

entrez la description de l'image ici

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
la source
Modification de la façon dont vous formez tpeut sauver deux octets: t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Puisque le motif est presque le même pour les deux, je me demande s'il y a un moyen de l'utiliser ..
Kade
Peut-être changer if c>"E":pour if"E"<c:enregistrer un octet?
ETHproductions
1

MSWLogo (version 6.5b), 136 octets

Basé sur le programme final de courbe de Hilbert ici .

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

Une fonction hest définie, qui prend le nombre d'itérations :n(basé sur 1), l'angle :a, la longueur :l. Il est récursif, appelant une itération inférieure de lui-même avec l'angle :aannulé dans deux cas pour obtenir l'orientation correcte.

  • rt :a, lt :atournez la tortue (triangle truc dont le chemin est tracé) à droite, à gauche par :adegrés.
  • fd :lfait avancer la tortue par :létapes.

Enfin, la fonction est appelée: h 5 90 9. La tortue peut être caché pour un supplément de 2 octets, ht.

(5-1) -ème itération

pour Monica
la source
Que se passe-t-il dans le coin supérieur gauche?
flawr
@flawr C'est la tortue. Il peut être masqué en ajoutant ht.
pour Monica
1

Mathematica 128 octets

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

Remplacez les 4 ci-dessus par un nombre différent d'itérations si vous le souhaitez.

Fait en tant que système Lindenmayer avec des séquences entières plutôt que des séquences de chaînes, la deuxième règle de production n'est donc que le négatif de la première règle. Cette version fait 151 octets.

Le port du code MATLAB de Jonas Lundgren n'est que de 128 octets.

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]

Je vois que dans une future version de Mathematica, cela peut devenir très court, quelque chose comme:

Graphics@HilbertCurve[n]

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

Kelly Lowder
la source
1

LindenMASM , 63 octets

Une autre question avec une réponse LindenMASM? Impressionnant!

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

Encore une fois, en raison de quelques bugs de dessin avec Python turtle, parfois lorsque vous exécutez cela, le dessin entier n'est pas là. Cependant, vous pouvez voir que cela fonctionne réellement:

4ème itération

Kade
la source