Tu tarea para hoy: ¡dibuja una curva de dragón!
En caso de que no sepas qué es Dragon Curve, aquí hay un video introductorio de ViHart (¡Realmente genial, mira!)
Su tarea: dibujar una curva de dragón, iterada al menos 9 veces. No tiene que mostrar las iteraciones 1 a 9, solo tiene que mostrar la curva final producida después de completar (al menos) 9 iteraciones. La curva debe dibujarse como líneas rectas que conectan los puntos en la curva; la salida debe coincidir con una de las imágenes a continuación que muestra 9 o más iteraciones (hasta reflexión, rotación, escala y variación en el ancho de línea, color de línea y color de fondo). Su salida debe ser lo suficientemente grande como para que las líneas individuales y los "cuadros" que forman puedan distinguirse entre sí; Si dos líneas no se cruzan en la curva, no deberían ocupar los mismos píxeles o adyacentes en la salida (debe haber al menos un píxel del fondo visible entre ellos). Puede mostrar la imagen en la pantalla o guardar la imagen en un archivo aceptado. La salida debe ser gráfica, no puede ser arte ASCII.
El código más corto en bytes gana, sin embargo , incluir directivas para bibliotecas no debe incluirse en el recuento de bytes, y puede usar bibliotecas de gráficos u otras bibliotecas escritas para el idioma de su elección si se escribieron antes de la publicación.
Incluya una imagen de la salida de su programa.
Omita este párrafo si vio el video:Para aquellos de ustedes que decidieron no ver el video, a continuación se muestran las primeras 12 iteraciones de la curva del dragón. Para los propósitos de esta tarea, una curva de dragón es una curva generada por la siguiente regla: tomar el punto final de la curva actual, crear una segunda curva girada 90 grados alrededor de ese punto final para que el punto final del original curva es el punto de partida de la nueva curva, y une las dos curvas en una sola curva donde se encuentran. En las imágenes que se muestran a continuación, cada nueva iteración se genera girando la iteración anterior 90 grados en sentido horario alrededor del punto final de cada iteración. Cuando la curva se muestra en la pantalla, no es obvio qué extremo cuenta como el "punto final", sin embargo, cuando la curva se almacena como una matriz de puntos, es fácil definir el "punto final" como el último punto en la matriz
El arte ascii es apreciado, pero no aceptado: esta es una salida gráfica, no ascii-art.
fuente
Respuestas:
x86, MSDOS, 16 bytes
Escribí esto hace un tiempo, que yo sepa, la rutina más pequeña para producir un dragón fractal. No utiliza iteraciones reales, sino que traza cada píxel discreto contenido dentro del fractal directamente, mostrando la imagen final . Se incluye con muchas otras pequeñas producciones en este paquete . La versión de 16 bytes fue el final de mi esfuerzo para lograr que el dragón fractal fuera lo más pequeño posible, comenzando 2014 con esta producción de 32 bytes .
Maleficio
Código
fuente
Python 2/3,
1691671501119878 BytesTenga en cuenta que la importación no está incluida en el recuento de bytes, de acuerdo con las especificaciones de desafío.
Gracias a @AlexHall por guardar 39 (!) Bytes y @ nedla2004 por otros 13
Comienza generando una lista o giros a la derecha (90) y a la izquierda (-90), luego pasa por la lista y mueve la tortuga.
Salida generada:
EDITAR: Si esto es demasiado aburrido, mire, agregue
speed(0)
justo antes del primerofd(5)
. Funcionará igual, excepto que la tortuga se moverá mucho más rápido.fuente
Logo, 43 bytes
Pruebe con el intérprete en http://www.calormen.com/jslogo/#
Esto utiliza el mismo principio que mi respuesta anterior de arte ASCII y la fórmula en wikipedia, excepto que invertí la dirección para que coincida con la imagen en la pregunta:
bitand :i -:i
encuentra el bit menos significativo dei
. Dividimosi
por esto a lai
derecha la cantidad requerida, dando el número impar requeridok
. No hay necesidad de distinguir entre giros a la izquierda y a la derecha; simplemente giramos a la izquierda pork*90
grados y confiamos en el hecho de que la rotación es una operación de módulo 360 para realizar el módulo por nosotros.Salida
use
ht
para ocultar tortugas si es necesario.Salida (modificada)
A continuación se muestra cómo la curva es un solo filamento.
fuente
LindenMASM , 51 Bytes
LindenMASM fue un lenguaje que creé para un desafío hace un tiempo que vivirá para siempre en el Sandbox. Utiliza el concepto de sistemas Lindenmayer para dibujar cosas como curvas de dragón, plantas fractales, triángulos de Sierpinski, etc.
El código fuente es el siguiente:
Para configurar esto,
n = 6
por ejemplo:Esto produce la siguiente imagen a través de Python 3
turtle
:Puede haber una ligera diferencia de numeración para las iteraciones, ya que en el sistema Lindenmayer la primera iteración es una sola línea. Esto es lo que parece
n = 10
:Solo por diversión, así es como se ve con 15 generaciones (con una instrucción adicional
MOV 2
para hacerlo un poco más pequeño):Una vez que obtienes hasta 20 generaciones (con
MOV 0.5
), ya no puedes ver las líneas, y se necesitan MUCHOS pasos para crear (pares de+-
y-+
no están optimizados). Esto es lo que obtienes:Tenga en cuenta que el intérprete actual puede presentar problemas gráficos para pequeñas cantidades de generaciones, es decir, posiblemente no dibujar en la pantalla. Desafortunadamente, cuando se creó este intérprete, no hubo problemas, un posible cambio en Python 3 podría haber causado esto o podría ser mi sistema
fuente
Baja carga, 196 bytes
Pensé que podría ser interesante probar este desafío en un esolang de baja potencia; Underload funciona bastante bien para un lenguaje con un número tan bajo de comandos.
El resultado es un archivo SVG con etiquetas muy anidadas y algunos atajos de golf. Hasta ahora, no he encontrado un navegador que pueda mostrarlo (Firefox se cuelga durante varios minutos tratando de cargarlo, y tanto Firefox como Chromium muestran una pantalla en blanco). La mayoría de los programas de procesamiento de imágenes tampoco pueden cargarlo (lo que dificulta la conversión a otro formato), pero logré cargarlo en el visor de imágenes Eye of Gnome (que es parte de la instalación predeterminada en Ubuntu). Así que tomé una captura de pantalla de la imagen para que pueda verla (la imagen real tiene un fondo transparente, pero en realidad no puede capturar la pantalla transparente):
Necesitamos especificar el tamaño de la imagen explícitamente. Recogiendo una orientación adecuada para la imagen, dibujo todo a la talla mínima legal, y haciendo el mínimo número de iteraciones especificados por el desafío, nos da una imagen que sólo encaja en 99 píxeles de ancho, el ahorro de un byte. Es agradable cuando las cosas funcionan así.
El algoritmo general utilizado para dibujar la imagen es mantener dos variables (Underload no nombra las variables, pero pensé en ellas como x e y ), ambas inicialmente vacías. Luego, reemplazamos repetidamente ( x , y ) con ( x , gire a la izquierda y avance, y ) y ( x , gire a la derecha y avance, y ). Después de diez iteraciones, tanto x como y mantienen una curva de dragón de nueve iteraciones.
También hay algunas micro optimizaciones y trucos específicos de subcarga. Para evitar perder el tiempo con la parte superior de la pila, cada iteración del bucle, comenzamos combinando x e y en la función "devolver la cadena creada concatenando: x , una instrucción de giro, el argumento de la función, un movimiento- instrucción hacia adelante, y y ". Esta función solo ocupa un espacio en la pila, por lo que podemos duplicarlo, llamarlo
-90
como argumento, intercambiar el valor de retorno debajo del duplicado y llamarlo90
como argumento, para obtener nuevos valores para x e ysin necesidad de tocar más que los dos elementos superiores de la pila (que son, con mucho, los más accesibles). Esta función es generada por código en tiempo de ejecución. El generador en sí también se genera con código en tiempo de ejecución, para permitirle reutilizar la cadena<g transform="translate
que también se usa para establecer el origen de la imagen. Primero generamos todas las etiquetas abiertas, y luego, dado que todas las etiquetas de cierre son justas</g>
, podemos generar 1024 etiquetas de cierre simplemente repitiendo la cadena, sin preocuparnos de hacer coincidirlas con las etiquetas abiertas. (Escribir números de manera eficiente en Underload es un problema interesante por derecho propio;(:*)::*:**:*
sin embargo, es probablemente la forma más eficiente de escribir 1024, traduciéndose en "2 a la potencia de (1 + 2 × 2) × 2".Underload no tiene ninguna biblioteca de gráficos, por lo que produzco SVG usando una combinación de líneas de dibujo en una posición fija y girando la imagen alrededor de un punto dado; en lugar de girar la pluma, giramos el papel. La idea es que dibujando una línea, girando la imagen completa, dibujando otra línea, girando la imagen nuevamente, etc., podemos simular efectivamente gráficos de tortuga sin tener que hacer ningún cálculo ni usar ninguna biblioteca de gráficos, ya que todas las líneas se dibujan en el mismo lugar Por supuesto, eso significa que tenemos algunas etiquetas de rotación de imagen muy anidadas, lo que confunde a muchos espectadores SVG.
Diseñar la imagen contaría contra el recuento de bytes, por lo que necesitaba dar el estilo mínimo necesario para mostrar la imagen. Esto resulta ser
stroke="#"
, que se traduce más o menos como "la línea debe ser de algún color"; esto parece expandirse para dibujarlo en negro. (Normalmente, especificaría el color como, por ejemplo, "# 000".) El fondo es transparente de forma predeterminada. No especificamos un ancho de trazo, pero la elección elegida por Eye of Gnome deja todo visible.Muchos intérpretes de Underload luchan con este programa, por ejemplo, el de Try It Online se bloquea, porque genera algunas cadenas muy grandes internamente. Sin embargo, el intérprete original de Underload en línea funciona. (Curiosamente, el primer intérprete estaba en línea, por lo que el idioma se podía usar en línea antes de que se pudiera usar sin conexión).
Algo que me inquieta un poco es que solo parece haber 1023 segmentos de línea aquí, y esperaríamos 1024. Podría ser que uno de los segmentos al final no se dibuje con este algoritmo (sería dibujado en la siguiente iteración). Si eso es descalificador, puede ser posible adaptar el programa, pero podría terminar considerablemente más tiempo. (No es como si este desafío fuera a ganar la competencia de todos modos; ya hay varias entradas más cortas).
fuente
MATL , 26 bytes
Si se aceptan diferentes escalas en los dos ejes, el código se puede reducir a 19 bytes:
Las siguientes figuras corresponden a la versión de igual escala (26 bytes).
El código anterior produce la novena iteración (basada en 0), es decir, la décima imagen en el desafío:
Para otros valores, cambie el
9
código o reempláceloi
para tomar el número como entrada del usuario. Por ejemplo, el resultado para13
es:Explicación
Esto usa un bucle para construir gradualmente una matriz de los pasos seguidos por la curva en el plano complejo. Por ejemplo, los dos primeros pasos son
1j
(arriba) y-1
(izquierda).En cada iteración, la matriz de pasos hasta el momento se copia. La copia de la matriz se invierte , se multiplica por
1j
(para rotar 90 grados) y se concatena al original.Después del ciclo, una suma acumulativa de los pasos da los puntos reales, que luego se trazan en el plano complejo.
fuente
Mathematica 86 bytes
Cómo funciona:
{1,-1}
salidas{1,-1}
. Básicamente "lo empuja a la pila". Este valor se puede recuperar con%
.r=Reverse
básicamente solo cambia el nombre de la función Reverse porque la uso dos veces en el código. ElGraphics@Line@
solo toma una lista de puntos y dibuja una línea que los conecta. El verdadero meollo del problema que ocurre en este segmento de código:Nest[Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&,{{0,0},%},9]
. Déjame decirte que ese segmento es complicado como f ****** ck.Nest
Esto es lo que hace:Nest[f,x,9]
genera el resultado de la llamadaf[f[f[f[f[f[f[f[f[x]]]]]]]]]
.En mi código, este primer argumento
f
es:,Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&
el segundo argumentox
es{{0,0},%}
(que se evalúa como{{0,0},{1,-1}}
), y el tercer argumento esn
, que es solo 9 (que solo aplicará el primer argumento al segundo argumento 9 veces).La parte más compleja de todas es este primer argumento:
Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&
que es un desorden gigante de azúcar sintáctico casi puro. Yo estaba realmente abusando de azúcar sintáctico de Mathematica para éste. Esa línea de código representa la versión matemática de una función anónima, excepto para acortar cosas, en realidad definí dos funciones anónimas separadas dentro de esa función anónima. Sí, eso es legal, amigos. Vamos a desglosarlo.Join
Toma dos argumentos. El primero esl=Last@#;h=#-l&/@#
, y el segundo esr[r@#%&/@h]
.El primer argumento de Join: dentro de la función anónima "principal",
#
hay una lista de todos los puntos en la iteración actual en la curva. Entoncesl=Last@#;
significa "Toma el punto en la lista de puntos que recibiste como entrada y asigna ese punto a la variablel
. El siguiente segmentoh=#-l&/@#
, es un poco más complejo. Significa" Tienes una función. Esta función toma un punto como entrada, lo restal
y devuelve el resultado. Ahora, aplique esa función a cada elemento en la lista de puntos que recibió como entrada para generar una lista de puntos desplazados, y asigne esa nueva lista a la variableh
.El segundo argumento de Join:
r[r@#%&/@h]
tiene literalmente la sintaxis más compleja que he escrito. No puedo creer que ningún segmento de código pueda contener algo como@#%&/@
: ¡parece que estoy maldiciendo como un personaje de dibujos animados en medio de un programa! Pero es posible desglosarlo. Recuerde:r[x]
toma una lista de puntos y la devuelve en orden inverso.r@#%&
es una función anónima que invierte su entrada, luego la multiplica por el valor almacenado en%
(que es{1,-1}
) y devuelve el resultado. Básicamente gira su entrada 90 grados, pero en un código tan corto como podría escribir. Luegor@#%&/@h
significa "Mostrar una nueva lista que es cada puntoh
girado 90 grados".Entonces, en general,
Join[l=Last@#;h=#-l&/@#,r[r@#*%&/@h]]&
es una función que toma una lista de puntos como entrada y agrega esa misma lista de puntos rotados 90 grados para obtener la siguiente iteración de la curva. Esto se repite 9 veces para obtener la curva del dragón. Luego, la lista resultante de puntos se dibuja en la pantalla como una línea. Y la salida:fuente
0{,}
... funciona porque0 x
es0
para casi cualquierx
y{,}
es azúcar sintáctico para{Null,Null}
.Python 2, 43 bytes
Esta respuesta es de 43 bytes sin incluir la declaración de importación y se basa en gran medida en la respuesta del logotipo de Level River St y su uso
i/(i&-i)
en su código. Pruébelo en línea en trinket.ioAquí hay una imagen de la salida.
fuente
The shortest code in bytes wins, however include directives for libraries shouldn't be included in the byte count, and you may use graphics libraries or other libraries written for your language of choice if they were written before the posting.
Mathematica,
5655 bytesExplicación: OEIS A034947
Solo por diversión, aquí hay una versión en color de la 19ª iteración.
fuente
Mathematica, 63 bytes
Utilizando
AnglePath
fuente
HTML + JavaScript, 182
fuente
Diagramas Haskell +, 179 bytes
La salida es un archivo svg de 99 píxeles de ancho con fondo transparente (una imagen de 9 píxeles de ancho tendría un trazo demasiado grueso para reconocer algo). Aquí se vuelve a escalar y se compone sobre un fondo blanco:
fuente
tosh , 518 bytes
tosh es Scratch , pero con texto en lugar de bloques. Con 518 bytes, esta respuesta es probablemente incluso peor que Java.
Esta respuesta utiliza la misma lógica que la respuesta de Python de @ Theo , pero con cadenas de "L" y "R" en lugar de números, ya que las capacidades de la lista de Scratch (y por lo tanto tosh) son horribles.
Puede ejecutarlo como un proyecto Scratch aquí . (Tosh compila proyectos Scratch)
Explicación:
Esta primera parte hace que el programa se ejecute cuando se hace clic en la bandera verde (
when flag clicked
), establece la variable de ruta en "R" y obtiene el sprite y la etapa en el estado adecuado para que estén listos para dibujar.Ahora llegamos al código de generación de ruta. Utiliza la misma lógica que la respuesta de Python de @ Theo , excepto con cadenas de "R" y "L" en lugar de números, y usamos bucles anidados en lugar de listas de comprensión.
Finalmente, dibujamos la ruta pasando por cada letra de la variable de ruta y girando hacia la izquierda o hacia la derecha según la letra.
fuente