Arte ASCII del día # 2 - Flow Snakes

32

Una serpiente de flujo, también conocida como curva de Gosper , es una curva fractal, que crece exponencialmente en tamaño con cada orden / iteración de un proceso simple. A continuación se detallan los detalles de la construcción y algunos ejemplos de varios pedidos:

Pedido 1 serpiente de flujo :

____
\__ \
__/

Orden 2 serpiente de flujo :

      ____
 ____ \__ \
 \__ \__/ / __
 __/ ____ \ \ \
/ __ \__ \ \/
\ \ \__/ / __
 \/ ____ \/ /
    \__ \__/
    __/

Orden 3 serpiente de flujo :

                 ____
            ____ \__ \
            \__ \__/ / __
            __/ ____ \ \ \    ____
           / __ \__ \ \/ / __ \__ \
      ____ \ \ \__/ / __ \/ / __/ / __
 ____ \__ \ \/ ____ \/ / __/ / __ \ \ \
 \__ \__/ / __ \__ \__/ / __ \ \ \ \/
 __/ ____ \ \ \__/ ____ \ \ \ \/ / __
/ __ \__ \ \/ ____ \__ \ \/ / __ \/ /
\ \ \__/ / __ \__ \__/ / __ \ \ \__/
 \/ ____ \/ / __/ ____ \ \ \ \/ ____
    \__ \__/ / __ \__ \ \/ / __ \__ \
    __/ ____ \ \ \__/ / __ \/ / __/ / __
   / __ \__ \ \/ ____ \/ / __/ / __ \/ /
   \/ / __/ / __ \__ \__/ / __ \/ / __/
   __/ / __ \ \ \__/ ____ \ \ \__/ / __
  / __ \ \ \ \/ ____ \__ \ \/ ____ \/ /
  \ \ \ \/ / __ \__ \__/ / __ \__ \__/
   \/ / __ \/ / __/ ____ \ \ \__/
      \ \ \__/ / __ \__ \ \/
       \/      \ \ \__/ / __
                \/ ____ \/ /
                   \__ \__/
                   __/

Construcción

Considere el orden 1 Flow Snake que se construirá a partir de una ruta que contiene 7 bordes y 8 vértices (etiquetados a continuación. Ampliado para mayor factibilidad):

4____5____6
 \         \
 3\____2   7\
       /
0____1/

Ahora, para cada orden siguiente, simplemente reemplace los bordes con una versión girada de este patrón de orden 1 original. Use las siguientes 3 reglas para reemplazar los bordes:

1 Para un borde horizontal, reemplácelo con la forma original como está:

________
\       \
 \____   \
     /
____/

2 Para un /borde ( 12en la construcción anterior), reemplácelo con la siguiente versión girada:

 /
/   ____
\  /   /
 \/   /
     /
____/

3 Para un \borde ( 34y 67superior), reemplácelo con la siguiente versión girada:

 /
/   ____ 
\   \   \
 \   \   \
  \  /
   \/

Entonces, por ejemplo, el orden 2 con vértices del orden 1 etiquetado se verá como

            ________
            \       \
  ________   \____   \6
  \       \      /   /
   \____   \5___/   /   ____
       /            \   \   \
  4___/   ________   \   \   \7
 /        \       \   \  /
/   ____   \____   \2  \/
\   \   \      /   /
 \   \   \3___/   /   ____
  \  /            \  /   /
   \/   ________   \/   /
        \       \      /
         \____   \1___/
             /
        0___/

Ahora, para cualquier orden superior, simplemente divida el nivel actual en bordes de longitudes 1 /, 1 \o 2 _y repita el proceso. Tenga en cuenta que incluso después de la sustitución, los vértices comunes entre dos bordes consecutivos siguen coincidiendo.

Reto

  • NDebe escribir una función de un programa completo que reciba un número entero único a través del argumento STDIN / ARGV / function o el equivalente más cercano e imprima la orden NFlow Snake en STDOUT.
  • El entero de entrada siempre es mayor que 0.
  • No debe haber espacios iniciales que no sean parte del patrón.
  • No debe haber espacios finales o suficientes espacios finales para rellenar el patrón para llenar completamente el rectángulo límite mínimo.
  • La nueva línea final es opcional.

Hechos graciosos

  • Flow Snakes es un juego de palabras de Snow Flakes, que este patrón se asemeja al orden 2 y superior
  • El flujo y las serpientes realmente juegan un papel en el patrón, ya que el patrón se compone de un solo camino que fluye a lo largo.
  • Si observa con cuidado, el patrón de orden 2 (y también superior) se compone de rotaciones del patrón de orden 1 pivotado en el vértice común del borde actual y el borde anterior.
  • Hay una variante no ASCII de Flow Snakes que se puede encontrar aquí y en varios otros lugares.

Este es el código más corto en bytes gana!


Tabla de clasificación

La primera publicación de la serie genera una tabla de clasificación.

Para asegurarse de que sus respuestas aparezcan, comience cada respuesta con un título, utilizando la siguiente plantilla de Markdown:

# Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

# Ruby, <s>104</s> <s>101</s> 96 bytes
Optimizador
fuente
Si entiendo correctamente, las formas 1, 2, 3 se amplían 2 veces, por lo que la fila inferior en 2 debe estar hecha de 4 puntos, no 3.
edc65
@ edc65 Las formas en los ejemplos tienen un tamaño perfecto. Si está hablando de la parte de Construcción, sí, que está ampliada y hay 3 guiones bajos para que el número de borde ocupe el 4to lugar
Optimizador
Pero no hay números de borde en la forma 2 (en la parte de construcción, sí). La parte inferior de la forma 2 debe ser igual a la parte inferior de la forma 1.
edc65
@ edc65 ¡Ah! ¡Fijo!
Optimizador de
3
Leí el título como "Snow Flakes" y ni siquiera noté el título real hasta que llamó la atención sobre la diferencia.
mbomb007

Respuestas:

4

CJam, 144 bytes

0_]0a{{_[0X3Y0_5]f+W@#%~}%}ri*{_[YXW0WW]3/If=WI6%2>#f*.+}fI]2ew{$_0=\1f=~-
"__1a /L \2,"S/=(@\+\~.+}%_2f<_:.e>\:.e<:M.-:)~S*a*\{M.-~3$3$=\tt}/zN*

Nueva línea agregada para evitar el desplazamiento. Pruébalo en línea

El programa funciona en varios pasos:

  1. El fractal inicial (orden 1) se codifica como una secuencia de 7 ángulos (conceptualmente, múltiplos de 60 °) que representan la dirección del movimiento.
  2. El fractal se "aplica" a un segmento horizontal (orden 0 fractal) N veces para generar todos los "movimientos" en el orden N fractal
  3. A partir de [0 0], los movimientos se traducen en una secuencia de puntos con coordenadas [xy]
  4. Cada segmento (par de puntos) se convierte en 1 o 2 [xyc] tripletes, que representan el carácter c en las coordenadas x, y
  5. Se determina el rectángulo delimitador, se ajustan las coordenadas y se genera una matriz de espacios.
  6. Para cada triplete, el carácter c se coloca en la posición x, y en la matriz, y la matriz final se ajusta para la salida
aditsu
fuente
Esta respuesta es lo suficientemente larga como para beneficiarse de la codificación de bytes: goo.gl/D1tMoc
Dennis
@ Dennis No estoy seguro de que haya terminado de jugar golf ... ¿y por qué lo pusiste en un bloque?
aditsu
No estoy realmente seguro ... Su respuesta es bastante impresionante. Pasé un día entero tratando de hacer esto bien.
Dennis
@ Dennis Gracias; por cierto, ¿crees que generalmente está bien usar caracteres no imprimibles / de control? Normalmente trato de evitarlos
aditsu
Si puedo evitarlos sin aumentar el número de bytes, lo hago. Pero más corto es más corto. : P En casos como este donde comprimo el código en sí mismo en lugar de alguna cadena o matriz, generalmente incluyo ambas versiones en la respuesta.
Dennis
16

Python 2, 428 411 388 bytes

Este fue bastante complicado. Los patrones no conservan sus proporciones después de cada paso, lo que significa que es muy difícil producir procesalmente una imagen de su predecesor. Lo que hace este código, aunque es bastante ilegible después de un intenso golf matemático, es dibujar la línea de principio a fin utilizando la Dfunción definida recursivamente .

El tamaño también fue un problema, y ​​terminé comenzando en el medio de un 5*3**ncuadrado echado a un lado y recortando cosas después, aunque si puedo pensar en una mejor manera de calcular el tamaño, podría cambiarlo.

n=input();s=5*3**n
r=[s*[" "]for i in[0]*s]
def D(n,x,y,t=0):
 if n<1:
    x-=t%2<1;y+=t%3>1;r[y][x]='_/\\'[t/2]
    if t<2:r[y][x+2*t-1]='_'
    return[-1,2,0,1,0,1][t]+x,y-(2<t<5)
 for c in[int(i)^t%2for i in"424050035512124224003"[t/2::3]][::(t^1)-t]:x,y=D(n-1,x,y,c)
 return x,y
D(n,s/2,s/2)
S=[''.join(c).rstrip()for c in r]
for l in[c[min(c.find('\\')%s for c in S):]for c in S if c]:print l
KSab
fuente
Wow, esto es asombroso. ¿Quieres probar AAoD # 1?
Optimizador
r=[s*[" "]for i in range(s)]-> r=[[" "]*s]*s]afeitará algunos bytes
sirpercival
1
@sirpercival desafortunadamente eso no funcionará debido a cómo se *repiten los objetos mutables .
grc
oh, claro, lo olvidé
sirpercival
Puede guardar algunos bytes en línea l, cambiando print'\n'.join()a la impresión dentro de un bucle for, usando return[...][t]+x,y eliminando los paréntesis (t%2). Además, podría usarlo min(c.find('\\')%s for c in S)si cambia el nombre de la lista Spara que no sobrescriba el valor inicial de s.
grc
12

JavaScript ( ES6 ), 356362 370

Esa es una difícil ...

Cada forma se almacena como una ruta. Hay 6 bloques de construcción básicos (3 + 3 hacia atrás)

  • 0diagonal arriba izquierda a abajo derecha ( 4hacia atrás)
  • 1diagonal inferior izquierda a arriba derecha ( 5hacia atrás)
  • 2horizontal de izquierda a derecha ( 6hacia atrás)

Para cada uno, hay un paso de reemplazo que se aplicará al aumentar el orden:

  • 0-> 0645001(hacia atrás 4-> 5441024)
  • 1-> 2116501(hacia atrás 5-> 5412556)
  • 2-> 2160224(hacia atrás 6-> 0664256)

valores prellenados en la hmatriz, incluso si los elementos 4..6 se pueden obtener de 0..2 usando

;[...h[n]].reverse().map(x=>x^4).join('')

Para obtener la forma para el orden dado, la ruta se construye en la variable p aplicando las sustituciones repetidamente. Luego, el bucle principal itera en la variable p y dibuja la forma dentro de la matriz g [], donde cada elemento es una fila.
Comenzando en la posición (0,0), cada índice puede volverse negativo (índice y en órdenes altas). Evito que los índices negativos y cambien toda la matriz g cada vez que encuentro un valor negativo de y. No me importa si el índice x se vuelve negativo, ya que en JS se permiten índices negativos, solo que es un poco más difícil de administrar.
En el último paso, escaneo la matriz principal usando .map, pero para cada fila necesito usar un bucle explícito para (;;) usando la bvariable que contiene el menor índice x alcanzado (que será <0).
En elconsole.log En la versión hay una práctica nueva línea principal, que se puede convertir fácilmente en una nueva línea final intercambiando 2 filas, como en la versión de fragmento.

f=o=>{
  g=[],x=y=b=0,
  h='064500192116501921602249954410249541255690664256'.split(9);
  for(p=h[2];--o;)p=p.replace(/./g,c=>h[c]);
  for(t of p)
    z='\\/_'[s=t&3],
    d=s-(s<1),
    t>3&&(x-=d,y+=s<2),
    y<0&&(y++,g=[,...g]),r=g[y]=g[y]||[],
    s?s>1?r[x]=r[x+1]=z:r[x]=z:r[x-1]=z,
    t<3&&(x+=d,y-=s<2),
    x<b?b=x:0;
  g.map(r=>
  {
    o+='\n';
    for(x=b;x<r.length;)o+=r[x++]||' '
  },o='');
  console.log(o)
}

Fragmento práctico para probar (en Firefox):

f=o=>{
  g=[],x=y=b=0,
  h='064500192116501921602249954410249541255690664256'.split(9);
  for(p=h[2];--o;)p=p.replace(/./g,c=>h[c]);
  for(t of p)
    z='\\/_'[s=t&3],
    d=s-(s<1),
    t>3&&(x-=d,y+=s<2),
    y<0&&(y++,g=[,...g]),r=g[y]=g[y]||[],
    s?s>1?r[x]=r[x+1]=z:r[x]=z:r[x-1]=z,
    t<3&&(x+=d,y-=s<2),
    x<b?b=x:0;
  g.map(r=>
  {
    for(x=b;x<r.length;)o+=r[x++]||' ';
    o+='\n'
  },o='');
  return o
}

// TEST

fs=9;
O.style.fontSize=fs+'px'

function zoom(d) { 
  d += fs;
  if (d > 1 && d < 40)
    fs=d, O.style.fontSize=d+'px'
}
#O {
  font-size: 9px;
  line-height: 1em;
}
<input id=I value=3><button onclick='O.innerHTML=f(I.value)'>-></button>
<button onclick="zoom(2)">Zoom +</button><button onclick="zoom(-2)">Zoom -</button>
<br>
<pre id=O></pre>

edc65
fuente
6

Haskell, 265 bytes

(?)=div
(%)=mod
t[a,b]=[3*a+b,2*b-a]
_#[0,0]=0
0#_=3
n#p=[352,6497,2466,-1]!!((n-1)#t[(s+3)?7|s<-p])?(4^p!!0%7)%4
0&_=0
n&p=(n-1)&t p+maximum(abs<$>sum p:p)
n!b=n&[1,-b]
f n=putStr$unlines[["__ \\/   "!!(2*n#t[a?2,-b]+a%2)|a<-[b-n!2+1..b+n!2+0^n?3]]|b<-[-n!0..n!0]]

(Nota: en GHC antes de 7.10, deberá agregar import Control.Applicativeo reemplazar abs<$>con map abs$).

Corre en línea en Ideone.com

f n :: Int -> IO ()dibuja la nserpiente de flujo de nivel . El dibujo se calcula en orden de mapa de bits en lugar de a lo largo de la curva, lo que permite que el algoritmo se ejecute en el espacio O (n) (es decir, logarítmico en el tamaño del dibujo). ¡Casi la mitad de mis bytes se gastan calculando qué rectángulo dibujar!

Anders Kaseorg
fuente
¡Ingresé y funciona ahora! ¡Agradable!
Optimizador
Resulta que esto anteriormente no se ejecutaba en Ideone.com porque estaba asumiendo Int de 64 bits. Solucionado ahora (sacrificando 2 bytes).
Anders Kaseorg
Está bien, ya que lo de iniciar sesión solo necesitaba mi ID de correo electrónico para la confirmación ...
Optimizer
5

Perl, 334 316 309

$_=2;eval's/./(map{($_,"\1"x7^reverse)}2003140,2034225,4351440)[$&]/ge;'x($s=<>);
s/2|3/$&$&/g;$x=$y=3**$s-1;s!.!'$r{'.qw($y--,$x++ ++$y,--$x $y,$x++ $y,--$x
$y--,--$x ++$y,$x++)[$&]."}=$&+1"!eeg;y!1-6!//__\\!,s/^$x//,s/ *$/
/,print for
grep{/^ */;$x&=$&;$'}map{/^/;$x=join'',map$r{$',$_}||$",@f}@f=0..3**$s*2

Parámetro tomado en la entrada estándar. Ponme a prueba .

nutki
fuente
5

Haskell, 469 419 390 385 365 bytes

la función f :: Int-> IO () toma un entero como entrada e imprime la serpiente de flujo

e 0=[0,0];e 5=[5,5];e x=[x]
f n=putStr.t$e=<<g n[0]
k=map$(53-).fromEnum
g 0=id
g n=g(n-1).(=<<)(k.(words"5402553 5440124 1334253 2031224 1345110 2003510"!!))
x=s$k"444666555666"
y=s$k"564645554545"
r l=[minimum l..maximum l]
s _[]=[];s w(x:y)=w!!(x+6):map(+w!!x)(s w y)
t w=unlines[["_/\\\\/_ "!!(last$6:[z|(c,d,z)<-zip3(x w)(y w)w,c==i&&d==j])|i<-r.x$w]|j<-r.y$w]
Damien
fuente
Esto produce 2 × figuras ampliadas. Creo que la pregunta es pedir las figuras más pequeñas en la parte superior, y solo usé figuras ampliadas 2 veces para explicar cómo se construye la serpiente de flujo.
Anders Kaseorg
Tienes razón. Lo corregí
Damien
Podría usar $en la definición de k, y reemplazar (!!)acon el (a!!)cual puede deshacerse de algunos paréntesis. Aparte de eso, parece que conoces muchos trucos por ti mismo. Niza
orgulloso Haskeller
4

C, 479 474 468 427 bytes

Supongo que no hay que vencer a los chicos de Perl y Haskell, pero dado que todavía no hay una presentación de C aquí:

#define C char
C *q="053400121154012150223433102343124450553245";X,Y,K,L,M,N,i,c,x,y,o;F(C*p,
int l,C d){if(d){l*=7;C s[l];for(i=0;i<l;i++)s[i]=q[(p[i/7]%8)*7+i%7];return F
(s,l,d-1);}x=0;y=0;o=32;while(l--){c=*p++%8;for(i=!(c%3)+1;i--;) {K=x<K?x:K;L=
y<L?y:L;M=x>M?x:M;N=y>N?y:N;y+=c&&c<3;x-=c%5>1;if(x==X&y==Y)o="_\\/"[c%3];y-=c
>3;x+=c%5<2;}}return X<M?o:10;}main(l){F(q,7,l);for(Y=L;Y<N;Y++)for(X=K;X<=M;X
++)putchar(F(q,7,l));}

Para ahorrar espacio en una llamada atoi (), el número de argumentos pasados ​​al programa se utiliza para el nivel.

El programa se ejecuta en O (n ^ 3) o peor; primero, la ruta se calcula una vez para encontrar las coordenadas mín. / máx., luego, para cada par (x, y), se calcula una vez para encontrar el carácter en esa ubicación específica. Terriblemente lento, pero ahorra en la administración de memoria.

Ejemplo ejecutado en http://codepad.org/ZGc648Xi

Zevv
fuente
Usar en X,Y,K,L,M,N,i,j,c;lugar de int X,Y,K,L,M,N,i,j,c;y en main(l)lugar devoid main(int l)
Spikatrix
Sí, gracias, ya me afeité y un poco más, pondré una nueva versión.
Zevv
El resultado en la última versión parece recortado y un poco apagado en los extremos.
Optimizador
Subí el blob equivocado, este debería estar bien.
Zevv
4

Python 2, 523 502 475 473 467 450 437 bytes

l=[0]
for _ in l*input():l=sum([map(int,'004545112323312312531204045045050445212331'[t::6])for t in l],[])
p=[]
x=y=q=w=Q=W=0
for t in l:T=t|4==5;c=t in{2,4};C=t<3;q=min(q,x);Q=max(Q,x+C);w=min(w,y);W=max(W,y);a=C*2-1;a*=2-(t%3!=0);b=(1-T&c,-1)[T&1-c];x+=(a,0)[C];y+=(0,b)[c];p+=[(x,y)];x+=(0,a)[C];y+=(b,0)[c]
s=[[' ']*(Q-q)for _ in[0]*(W-w+1)]
for t,(x,y)in zip(l,p):x-=q;s[y-w][x:x+1+(t%3<1)]='_/\_'[t%3::3]
for S in s:print''.join(S)

Pffft, me costó unas 3 horas, ¡pero fue divertido hacerlo!

La idea es dividir la tarea en múltiples pasos:

  1. Calcule todos los bordes (codificados como 0-5) en orden de aparición (es decir, desde el principio de la serpiente hasta el final)
  2. Calcule la posición para cada una de las aristas (y guarde los valores mínimo y máximo para x e y)
  3. Construya las cadenas en que consiste (y use los valores mínimos para compensar, de modo que no obtengamos índices negativos)
  4. Imprime las cuerdas

Aquí está el código en forma no golfizada:

# The input
n = int(input())

# The idea:
# Use a series of types (_, /, \, %), and positions (x, y)
# Forwards:   0: __  1: /  2: \
# Backwards:  3: __  4: /  5: \

# The parts
pieces = [
    "0135002",
    "0113451",
    "4221502",
    "5332043",
    "4210443",
    "5324551"
]
# The final types list
types = [0]
for _ in range(n):
    old = types
    types = []
    for t in old:
        types.extend(map(int,pieces[t]))

# Calculate the list of positions (and store the mins and max')
pos = []
top = False
x = 0
y = 0
minX = 0
minY = 0
maxX = 0
maxY = 0
for t in types:
    # Calculate dx
    dx = 1 if t < 3 else -1
    if t%3==0:
        dx *= 2         # If it's an underscore, double the horizontal size
    # Calculate dy
    top = t in {1, 5}
    dy = 0
    if top and t in {0, 3, 1, 5}:
        dy = -1
    if not top and t in {2, 4}:
        dy = 1
    # If backwards, add dx before adding the position to the list
    if t>2:
        x += dx
    # If top to bottom, add dy before adding the position to the list
    if t in {2,4}:
        y += dy
    # Add the current position to the list
    pos += [(x, y)]
    # In the normal cases (going forward and up) modify the x and y after changing the position
    if t<3:
        x += dx
    if t not in {2, 4}:
        y += dy
    # Store the max and min vars
    minX = min(minX, x)
    maxX = max(maxX, x + (t<3)) # For forward chars, add one to the length (we never end with __'s)
    minY = min(minY, y)
    maxY = max(maxY, y)

# Create the string (a grid of charachters)
s = [[' '] * (maxX - minX) for _ in range(maxY - minY + 1)]
for k, (x, y) in enumerate(pos):
    x -= minX
    y -= minY
    t = types[k]
    char = '/'
    if t % 3 == 0:
        char = '__'
    if t % 3 == 2:
        char = '\\'
    s[y][x : x + len(char)] = char

# Print the string
for printString in s:
    print("".join(printString))

Editar: cambié el idioma a python 2, para que sea compatible con mi respuesta para el n. ° 3 (y también ahorra 6 bytes más)

Matty
fuente
Buen trabajo; una simple mejora que podría hacer sería cambiar l.extend(x)a l+=x. También es probable que pueda usar codegolf.stackexchange.com/questions/54/… en lugar del .split()que usa (hice algo similar en mi respuesta)
KSab
@KSab Gracias, me siento realmente estúpido ahora por usarloextend
Matty
0

Pari / GP, 395

Recorriendo las posiciones de los caracteres x, y y calculando qué caracteres imprimir. Intentos moderados de minimizar, puntuado con espacios en blanco y comentarios despojados.

k=3;
{
  S = quadgen(-12);  \\ sqrt(-3)
  w = (1 + S)/2;     \\ sixth root of unity
  b = 2 + w;         \\ base

  \\ base b low digit position under 2*Re+4*Im mod 7 index
  P = [0, w^2, 1, w, w^4, w^3, w^5];
  \\ rotation state table
  T = 7*[0,0,1,0,0,1,2, 1,2,1,0,1,1,2, 2,2,2,0,0,1,2];
  C = ["_","_",  " ","\\",  "/"," "];

  \\ extents
  X = 2*sum(i=0,k-1, vecmax(real(b^i*P)));
  Y = 2*sum(i=0,k-1, vecmax(imag(b^i*P)));

  for(y = -Y, Y,
     for(x = -X+!!k, X+(k<3),  \\ adjusted when endpoint is X limit
        z = (x- (o = (x+y)%2) - y*S)/2;
        v = vector(k,i,
                   z = (z - P[ d = (2*real(z) + 4*imag(z)) % 7 + 1 ])/b;
                   d);
        print1( C[if(z,3,
                     r = 0;
                     forstep(i=#v,1, -1, r = T[r+v[i]];);
                     r%5 + o + 1)]) );  \\ r=0,7,14 mod 5 is 0,2,4
     print())
}

Cada personaje es el primero o el segundo de una celda hexagonal. Una ubicación de celda es un número complejo z dividido en base b = 2 + w con dígitos 0, 1, w ^ 2, ..., w ^ 5, donde w = e ^ (2pi / 6) sexta raíz de la unidad. Esos dígitos se mantienen como un distintivo de 1 a 7 y luego se toman de mayor a menor a través de una tabla de estado para la rotación neta. Esto está en el estilo del código de serpiente de flujo por Ed Shouten (xytoi) pero solo para la rotación neta, sin convertir los dígitos en un índice "N" a lo largo de la ruta. Las extensiones son relativas a un origen 0 en el centro de la forma. Mientras el límite no sea un punto final, estos son el medio de un hexágono de 2 caracteres y solo se necesita 1 de esos caracteres. Pero cuando el inicio y / o final de la serpiente son el límite X, se necesitan 2 caracteres, que es k = 0 inicio yk <3 final. Pari tiene "quads" como sqrt (-3) incorporado, pero lo mismo se puede hacer con partes reales e imaginarias por separado.

Kevin Ryde
fuente
1
Esto no satisface las reglas relativas al espacio en blanco inicial y final.
Anders Kaseorg
Gracias, lo modifiqué. Tu haskell me ganó por una hora en un ciclo x, y lo hizo. Debería haber publicado antes de esperar para ver si vendría más inspiración :-).
Kevin Ryde
Ahora se corta el final de la serpiente para k = 0, 1, 2. (Las matemáticas son irritantes de esa manera, tuve que lidiar con eso también)
Anders Kaseorg
Ah querida, cuando el punto final es el máximo x. Hmm
Kevin Ryde