Flocon de neige de Koch - CodeGolf

21

Le flocon de neige de Koch (également connu sous le nom d'étoile de Koch et d'île de Koch) est une courbe mathématique et l'une des premières courbes fractales à avoir été décrite. Il est basé sur la courbe de Koch, qui est apparue dans un article de 1904 intitulé "Sur une courbe continue sans tangentes, constructible à partir de la géométrie élémentaire" (titre français original: "Sur une courbe continue sans tangente, obtenue par une construction géométrique élémentaire") par le mathématicien suédois Helge von Koch.

entrez la description de l'image ici

Voici quelques représentations ascii de diverses itérations:

n=1
__
\/

n=2
__/\__
\    /
/_  _\
  \/

n=3
      __/\__
      \    /
__/\__/    \__/\__
\                /
/_              _\
  \            /
__/            \__
\                /
/_  __      __  _\
  \/  \    /  \/
      /_  _\
        \/ 

Puisqu'il y a évidemment une limite à la résolution de la représentation ascii, nous devons agrandir la taille du flocon de neige d'un facteur 3 pour chaque itération pour montrer le détail supplémentaire.

Écrivez le code le plus court pour sortir le flocon de neige dans le même style pour n = 4

Votre programme ne doit prendre aucune entrée.
Votre programme devrait écrire le flocon de neige sur la console.

grignoteur
la source
Koch-snowflake ..une balise .. c'est intéressant .. !! .. semble que vous
poserez
5
Trop court pour une réponse: wolframalpha.com/input/?i=koch+snowflake+4 : D
Dr. belisarius
1
La réponse acceptée doit-elle être modifiée? Il existe maintenant des solutions plus courtes.
Timwi

Réponses:

2

Python, 338 octets

#coding:u8
print u"碜䄎쀠ࢻ﬊翀蝈⼖㗎芰悼컃뚔㓖ᅢ鄒鱖渟犎윽邃淁挢㇌ꎸ⛏偾࿵헝疇颲㬤箁鴩沬饅앎↳\ufaa4軵몳퍋韎巃๧瓠깡未늳蒤ꕴ⁵ᦸ䥝両䣚蟆鼺伍匧䄂앢哪⡈⁙ತ乸ሣ暥ฦꋟ㞨ޯ⿾庾뻛జ⻏燀䲞鷗﫿".encode("utf-16be").decode("zlib")

Juste un autre exploit unicode

courir à ideone

VOUS
la source
5
D'accord, mais cela ferait sûrement plus de 300 octets de long sur le fichier source.
Timwi
le lien est rompu
Chiel ten Brinke
10

Python, 650 612 594 574 caractères

n='\n'
S='_a/G\F I\n'
A=dict(zip(S,('III','   ','__/','  G','\  ','F__','   ','III','')))
B=dict(zip(S,('III','   ','\  ',' aF','/a ','  G','   ','III','')))
C=dict(zip(S,('___','aaa','/  ','GII','II\\','  F','   ','III','')))
def T(s):
 a=b=c=d=r=u''
 for k in s:
    a+=A[k];b+=B[k];c+=C[k]
    if k=='I':a=a[:-3]+('II\\'if'a '==d[1:3]else'GII'if' a'==d[:2]else 3*k)
    d=d[3:]
    if k==n:d=c.replace('____','__/F').replace('aaaa','aa  ').replace('/  a','/a  ').replace('a  F','  aF');r+=a+n+b+n+d+n;a=b=c=''
 return r
print T(T(T('__\n\G\n'))).translate({97:95,71:47,73:32,70:92})

Cela fonctionne en agrandissant le triangle d'un facteur 3 à chaque fois. Pour ce faire, nous devons garder une trace de si chaque symbole est une limite gauche ou droite (par exemple, comment /est développé dépend de quel côté de /l'intérieur est). Nous utilisons des symboles différents pour les deux cas possibles, comme suit:

_: _, outside on the top
a: _, outside on the bottom
/: /, outside on the left
G: /, outside on the right
\: \, outside on the left
F: \, outside on the right
<space>: inside
I: outside

La dvariable gère le cas spécial où l'expansion d'un adoit s'étendre au 3x3 de la ligne suivante.

Keith Randall
la source
+1 pour avoir obtenu la première réponse au tableau. Je pense que vous pouvez remplacer les espaces doubles par un onglet dans la boucle for. Essayez également d'utiliser if k <"C" au lieu de K == "A" etc. Maintenant, je vais devoir regarder de plus près votre algorithme :)
gnibbler
Ne pouvez-vous pas supprimer les nombreuses instructions if avec un tableau associatif? Et peut-être que les instructions de remplacement chaînées peuvent être raccourcies avec un tableau.
Nabb
('acEei',r'_/\\ ')=> ('aecEi','_\/\ ')enregistre 1 de plus. Vous pouvez également consulter le unicode.translate().
gnibbler
Cela imprime également environ 18 nouvelles lignes avant le flocon de neige, mais je suppose que l'OP n'a pas précisé si autre chose que le flocon de neige peut être imprimé.
RomanSt
6

Code machine MS-DOS 16 bits: 199 octets

Décodez en utilisant ce site , enregistrez-le en tant que fichier 'koch.com' et exécutez à partir de l'invite de commande WinXP.

sCAAxo7ajsKLz/OquF9fulwvvUoBM9u+BADoiQDodgDocwDogADobQDoagDodwCK8TLSs0+I98cHDQrGRwIktAnNIf7GOO5+7MNWAVwBYwFsAXoBgwGJB4DDAsOIN/7D6QQA/suIF/7P6R0A/suAPyB1AogH/suIB8OBw/8AiDfpBgD+x4gX/sM4734Ciu84z30Cis/Dg8UIg8UCgf1WAXLzg+0Mw07/dgB0GV/o9v/o5v/o8P/o3f/o2v/o5//o1//o4f9Gww==

Mise à jour

Voici une version d'assembleur facile à lire:

  ; L-System Description
  ;
  ; Alphabet : F
  ; Constants : +, -
  ; Axiom : F++F++F
  ; Production rules: F -> F-F++F-F 
  ;
  ; Register usage:
  ;                             _        _
  ; bp = direction: 0 = ->, 1 = /|, 2 = |\, 3 = <-, 4 = |/_, 5 = _\|
  ; cl = min y, ch = max y
  ; bl = x (unsigned)
  ; bh = y (signed)
  ; si = max level

  ; clear data
  mov al,20h
  add dh,al
  mov ds,dx
  mov es,dx
  mov cx,di
  rep stosb
  mov ax,'__'
  mov dx,'/\'

  ; initialise variables
  mov bp,Direction0
  xor bx,bx
  mov si,4

  call MoveForward
  call TurnRight
  call TurnRight
  call MoveForward
  call TurnRight
  call TurnRight
  call MoveForward

  mov dh,cl
  xor dl,dl
  mov bl,79
OutputLoop:
  mov bh,dh
  mov w [bx],0a0dh
  mov b [bx+2],24h
  mov ah,9
  int 21h
  inc dh
  cmp dh,ch
  jle OutputLoop  
  ret

Direction0:
  dw MoveRight
  dw MoveUpRight
  dw MoveUpLeft
  dw MoveLeft
  dw MoveDownLeft
  dw MoveDownRight
Direction6:

MoveRight:
  mov w [bx],ax
  add bl,2
  ret

MoveUpRight:
  mov b [bx],dh
  inc bl
  jmp DecBHCheckY

MoveUpLeft:
  dec bl
  mov b [bx],dl
DecBHCheckY:  
  dec bh
  jmp CheckY

MoveLeft:
  dec bl  
  cmp b [bx],20h
  jne MoveLeftAgain
  mov [bx],al
MoveLeftAgain:
  dec bl  
  mov [bx],al
  ret

MoveDownLeft:
  add bx,255
  mov b [bx],dh
  jmp CheckY

MoveDownRight:
  inc bh
  mov b [bx],dl
  inc bl

CheckY:
  cmp bh,ch
  jle NoMaxChange
  mov ch,bh
NoMaxChange:  
  cmp bh,cl
  jge NoMinChange
  mov cl,bh
NoMinChange:  
  ret

TurnRight:
  add bp,8

TurnLeft:
  add bp,2

  cmp bp,Direction6
  jb ret
  sub bp,12
  ret

MoveForward:
  dec si
  push [bp]
  jz DontRecurse
  pop di
  call MoveForward
  call TurnLeft
  call MoveForward
  call TurnRight
  call TurnRight
  call MoveForward
  call TurnLeft
  call MoveForward
DontRecurse:
  inc si
  ret
Skizz
la source
Abolute magic :), s'il vous plaît aidez-moi à comprendre cela (au moins fournissez un lien sur ce que vous avez fait)
Aman ZeeK Verma
@Aman: Il utilise une description du système L de la courbe de Koch pour dessiner la sortie. Le niveau de détail est défini dans le registre SI bien que la taille soit limitée à 252 caractères par ligne. Vous devrez modifier le code d'impression pour obtenir des lignes de plus de 79 caractères (c'est-à-dire changer où il écrit les caractères '\ n $').
Skizz
peut également utiliser "scAA...w==".decode("base64")pour décoder en Python2 (ne fonctionne pas pour Python3)
gnibbler
+1 maintenant que j'ai une machine Windows pour l'exécuter. Y a-t-il une chance que vous puissiez inclure la version asm?
gnibbler
2
@mellamokb: euh, parce que tout le code source est peut-être disponible?
Skizz
4

Perl, 176 175 octets

Publier cela comme une réponse distincte car il utilise un fichier source binaire, ce qui est peut-être un peu tricheur. Mais étant donné que c'est toujours du code source Perl , je pense qu'il est remarquable qu'il bat la solution de code machine MS-DOS !

Source encodée en base64

JF89IsLApwag0dhnMmAmMEcGIAcGQNHYwsDRFLsQ0djCwKcGoNHYwsDRFDdbECYwcRUxe1DCwNEUuxDR2
CI7c14uXiR4PW9yZCQmOyQieCgkeD4+MykucXcoXCAvXyBfXy8gXC8gX18gX1wgLyBfXy9cX18pWyR4Jj
ddXmVnO3NeLnsyN31eJF89cmV2ZXJzZSQmO3l+L1xcflxcL347cHJpbnQkJi4kXy4kL15lZw==

Un peu plus lisible

Remplacez toutes les instances de /<[0-9a-f]+>/par les données binaires pertinentes:

# Raw data!
$_="<c2c0a706a0d1d86732602630470620070640d1d8c2c0d114bb10d1d8c2>".
   "<c0a706a0d1d8c2c0d114375b1026307115317b50c2c0d114bb10d1d8>";

# Decode left half of the snowflake (without newlines)
s^.^$x=ord$&;$"x($x>>3).qw(\ /_ __/ \/ __ _\ / __/\__)[$x&7]^eg;

# Reconstruct the right half and the newlines
s^.{27}^$_=reverse$&;y~/\\~\\/~;print$&.$_.$/^eg

Dans cette version, le flocon de neige est codé de la manière suivante:

  • Les 8 bits de chaque octet sont divisés comme suit:

    +---+---+---+---+---+---+---+---+
    |      5 bits       |   3 bits  |
    +---+---+---+---+---+---+---+---+
              R               C
    
  • Rcode une série d'espaces. La course la plus longue est de 27 caractères, donc toutes les courses tiennent sur 5 bits.

  • Ccode une séquence de caractères qui sont simplement recherchés dans le tableau littéral. (J'avais l'habitude d'avoir des encodages légèrement plus fous ici où le tableau contenait uniquement / \ _, mais le code Perl nécessaire pour le décoder était plus long ...)

  • J'ai de la chance que les données binaires ne contiennent aucun "/ 'ou \qu'il faudrait échapper. Je n'avais pas prévu ça. Mais même si c'était le cas, j'aurais probablement pu changer l'ordre des éléments du tableau pour résoudre ce problème.

  • Il est étonnant de voir à quel point cette solution est simple par rapport aux dizaines d'autres solutions que j'ai rencontrées avant d'en arriver là. J'ai expérimenté de nombreux codages au niveau du bit plus complexes que celui-ci, et il ne m'est jamais venu à l'esprit qu'un plus simple pourrait en valoir la peine simplement parce que le code Perl pour le décoder serait plus court. J'ai également essayé de compresser les répétitions dans les données en utilisant l'interpolation variable (voir l'autre réponse), mais avec la dernière version qui ne gagne plus de caractères.

Timwi
la source
3

Python, 284

for s in "eJyVkNENACEIQ/+dgg1YiIT9tzgENRyWXM4/pH1tIMJPlUezIiGwMoNgE5SzQvzRBq52Ebce6cr0aefbt7NjHeNEzC9OAalADh0V3gK35QWPeiXIFHKH8seFfh1zlQB6bjxXIeB9ACWRVwo=".decode('base64').decode('zlib').split('\n'):print s+'  '*(27-len(s))+'\\'.join([c.replace('\\','/')for c in s[::-1].split('/')])

Avec un peu plus d'espace:

for s in "eJyVkNENACEIQ/+dgg1YiIT9tzgENRyWXM4/pH1tIMJPlUezIiGwMoNgE5SzQvzRBq52Ebce6cr0aefbt7NjHeNEzC9OAalADh0V3gK35QWPeiXIFHKH8seFfh1zlQB6bjxXIeB9ACWRVwo=".decode('base64').decode('zlib').split('\n'):
  print s + '  '*(27-len(s)) + '\\'.join([c.replace('\\','/') for c in s[::-1].split('/')])

Le côté gauche est compressé; le côté droit est reproduit du côté gauche.

RomanSt
la source
3

Perl, 224 223 caractères

use MIME::Base64;$_=decode_base64 wsCnBqDR2GcyYCYwRwYgBwZA0djCwNEUuxDR2MLApwag0djCwNEUN1sQJjBxFTF7UMLA0RS7ENHY;s^.^$x=ord$&;$"x($x>>3).qw(\ /_ __/ \/ __ _\ / __/\__)[$x&7]^eg;s^.{27}^$_=reverse$&;y~/\\~\\/~;print$&.$_.$/^eg

Un peu plus lisible

use MIME::Base64;

# raw binary data in base-64-encoded form as a bareword
$_=decode_base64
    wsCnBqDR2GcyYCYwRwYgBwZA0djCwNEUuxDR2MLApwag0djCwNEUN1sQJjBxFTF7UMLA0RS7ENHY;

# Decode left half of the snowflake (without newlines)
s^.^$x=ord$&;$"x($x>>3).qw(\ /_ __/ \/ __ _\ / __/\__)[$x&7]^eg;

# Reconstruct the right half and the newlines
s^.{27}^$_=reverse$&;y~/\\~\\/~;print$&.$_.$/^eg

Comment ça marche

Pour une explication de la façon dont cela fonctionne, voir l'autre réponse dans laquelle je poste la même chose en binaire . Je suis vraiment désolé de ne pas générer le flocon de neige Koch, je le compresse juste ...

Versions précédentes

  • (359) Encodé tout le flocon de neige au lieu de juste la moitié gauche. Des espaces ont été inclus dans l'encodage des bits; pas encore de longueur. Utilisé plusieurs variables interpolées plus un @_tableau accessible à l'aide de s/\d/$_[$&]/eg. Les retours à la ligne ont été codés comme !.

  • (289) Première version qui n'encodait que la moitié gauche du flocon de neige.

  • (267) Première version qui utilisait l'encodage de longueur pour les espaces.

  • (266) Remplacer ' 'par $".

  • (224) Compression radicalement différente, codée en base-64. (Maintenant équivalent à la version binaire .)

  • (223) Je me suis rendu compte que je pouvais mettre l'impression à l'intérieur du dernier subst et ainsi enregistrer un point-virgule.

Timwi
la source