Copo de nieve de Koch - codegolf

21

El copo de nieve de Koch (también conocido como la estrella de Koch y la isla de Koch) es una curva matemática y una de las primeras curvas fractales que se han descrito. Se basa en la curva de Koch, que apareció en un artículo de 1904 titulado "En una curva continua sin tangentes, construible a partir de geometría elemental" (título original en francés: "Sur une courbe continue sans tangente, obtenue par une construction géométrique élémentaire") por el matemático sueco Helge von Koch.

ingrese la descripción de la imagen aquí

Aquí hay algunas representaciones ascii de varias iteraciones:

n=1
__
\/

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

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

Como obviamente hay un límite para la resolución de la representación ascii, debemos agrandar el tamaño del copo de nieve por un factor de 3 para cada iteración para mostrar el detalle adicional.

Escriba el código más corto para generar el copo de nieve en el mismo estilo para n = 4

Su programa no debe tomar ninguna entrada.
Su programa debe escribir el copo de nieve en la consola.

gnibbler
fuente
Koch-snowflake ... una etiqueta ... eso es interesante ... !! ... parece que dispararás más preguntas sobre esta etiqueta :)
Aman ZeeK Verma
55
Demasiado corto para una respuesta: wolframalpha.com/input/?i=koch+snowflake+4 : D
Dr. belisarius
1
¿Debería cambiarse la respuesta aceptada? Hay soluciones más cortas ahora.
Timwi

Respuestas:

2

Python, 338 bytes

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

Solo otra hazaña Unicode

correr en ideone


fuente
55
Es justo, pero seguramente eso haría que el archivo fuente tenga más de 300 bytes de longitud.
Timwi
el enlace está roto
Chiel ten Brinke
10

Python, 650 612 594 574 caracteres

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

Esto funciona expandiendo el triángulo por un factor de 3 cada vez. Para hacer eso, necesitamos hacer un seguimiento de si cada símbolo es un límite izquierdo o derecho (por ejemplo, cómo /se expande depende de qué lado del /interior se encuentre). Utilizamos diferentes símbolos para los dos casos posibles, de la siguiente manera:

_: _, 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 maneja el caso especial donde la expansión de un anecesita extenderse al 3x3 en la siguiente fila.

Keith Randall
fuente
+1 por obtener la primera respuesta en el tablero. Creo que puede reemplazar los espacios dobles con una pestaña en el bucle for. También intente usar if k <"C" en lugar de K == "A", etc. Ahora tendré que mirar más de cerca su algoritmo :)
gnibbler
¿No puedes eliminar las muchas declaraciones if con una matriz asociativa? Y tal vez las declaraciones de reemplazo encadenadas se pueden acortar con una matriz.
Nabb
('acEei',r'_/\\ ')=> ('aecEi','_\/\ ')ahorra 1 más. También puede consultar el unicode.translate().
gnibbler
Esto también imprime alrededor de 18 líneas nuevas antes del copo de nieve, pero supongo que el OP no especificó si se puede imprimir algo más que el copo de nieve.
RomanSt
6

Código de máquina de 16 bits de MS-DOS: 199 bytes

Decodifique usando este sitio , guárdelo como archivo 'koch.com' y ejecútelo desde el símbolo del sistema de 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==

Actualizar

Aquí hay una versión de ensamblador fácil de leer:

  ; 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
fuente
Magia absoluta :), por favor ayúdame a entender esto (al menos proporciona un enlace sobre lo que hiciste)
Aman ZeeK Verma
@Aman: utiliza una descripción del sistema L de la curva de Koch para dibujar la salida. El nivel de detalle se establece en el registro SI, aunque el tamaño está limitado a 252 caracteres por línea. Deberá modificar el código de impresión para obtener líneas de más de 79 caracteres (es decir, cambiar el lugar donde escribe los caracteres '\ n $').
Skizz
también se puede usar "scAA...w==".decode("base64")para decodificar en Python2 (no funciona para Python3)
gnibbler
+1 ahora que tengo una máquina con Windows para ejecutarlo. ¿Alguna posibilidad de que pueda incluir la versión ASM?
gnibbler
2
@mellamokb: err, porque todo el código fuente está disponible tal vez?
Skizz
4

Perl, 176 175 bytes

Publicar esto como una respuesta separada porque usa un archivo fuente binario, lo cual es quizás un poco engañoso. Pero teniendo en cuenta que sigue siendo el código fuente de Perl , creo que es notable que supere la solución de código de máquina de MS-DOS .

Fuente como codificada en base64

JF89IsLApwag0dhnMmAmMEcGIAcGQNHYwsDRFLsQ0djCwKcGoNHYwsDRFDdbECYwcRUxe1DCwNEUuxDR2
CI7c14uXiR4PW9yZCQmOyQieCgkeD4+MykucXcoXCAvXyBfXy8gXC8gX18gX1wgLyBfXy9cX18pWyR4Jj
ddXmVnO3NeLnsyN31eJF89cmV2ZXJzZSQmO3l+L1xcflxcL347cHJpbnQkJi4kXy4kL15lZw==

Algo más legible

Reemplace todas las instancias de /<[0-9a-f]+>/con los datos binarios relevantes:

# 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

En esta versión, el copo de nieve se codifica de la siguiente manera:

  • Los 8 bits en cada byte se dividen así:

    +---+---+---+---+---+---+---+---+
    |      5 bits       |   3 bits  |
    +---+---+---+---+---+---+---+---+
              R               C
    
  • Rcodifica una serie de espacios. La ejecución más larga es de 27 caracteres, por lo que todas las ejecuciones caben en 5 bits.

  • Ccodifica una secuencia de caracteres que simplemente se buscan en la matriz literal. (Solía ​​tener codificaciones ligeramente más locas aquí donde la matriz contenía solo / \ _, pero el código Perl necesario para decodificarla era más largo ...)

  • Tengo suerte de que los datos binarios no contengan ninguno "/ 'o \que necesite escapar. No planeé esto. Pero incluso si lo hiciera, probablemente podría haber cambiado el orden de los elementos en la matriz para solucionarlo.

  • Es sorprendente lo simple que se compara esta solución con las decenas de otras soluciones que pasé antes de llegar a esto. Experimenté con muchas codificaciones bit a bit diferentes más complejas que esta, y nunca se me ocurrió que una más simple podría valer la pena simplemente porque el código Perl para decodificarla sería más corto. También intenté comprimir repeticiones en los datos usando interpolación variable (ver la otra respuesta), pero con la versión más nueva que ya no gana caracteres.

Timwi
fuente
3

Pitón, 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('/')])

Con un poco más de espacio en blanco:

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('/')])

El lado izquierdo está comprimido; el lado derecho se reproduce desde el lado izquierdo.

RomanSt
fuente
3

Perl, 224 223 caracteres

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

Algo más legible

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

Cómo funciona

Para una explicación de cómo funciona, vea la otra respuesta en la que publico lo mismo en binario . Realmente lamento no estar generando el copo de nieve de Koch, solo comprimiéndolo ...

Versión anterior

  • (359) Codificó todo el copo de nieve en lugar de solo la mitad izquierda. Se incluyeron espacios en la codificación de bits; No hay longitud de carrera todavía. Se usaron varias variables interpoladas más una @_matriz a la que se accedió usando s/\d/$_[$&]/eg. Las líneas nuevas se codificaron como !.

  • (289) Primera versión que codificó solo la mitad izquierda del copo de nieve.

  • (267) Primera versión que usó codificación de longitud de ejecución para los espacios.

  • (266) Cambiar ' 'a $".

  • (224) Compresión radicalmente diferente, codificada como base-64. (Ahora equivalente a la versión binaria ).

  • (223) Comprendí que puedo poner la impresión dentro del último sustituto y así guardar un punto y coma.

Timwi
fuente