El camino del ñu


23

Golf un programa o función que proporciona la ubicación del ñu que comienza en el cuadrado en un tablero de ajedrez infinito que está numerado en una espiral cuadrada en sentido antihorario, donde el ñu siempre visita el cuadrado con el número más bajo ella puede llegar a lo que aún no ha visitado.nth1

Inspiración: The Trapped Knight y OEIS A316667 .

Editar: esta secuencia ahora está en el OEIS como A323763 .

El código puede producir la ubicación , las primeras ubicaciones, o generar la secuencia sin entrada.nthn

Siéntase libre de darle su ubicación después (o hasta) saltos en su lugar, pero si es así, indíquelo claramente en su respuesta y asegúrese de que una entrada de rinda (o si corresponde).nn=01[1]

Este es el , por lo que el objetivo es producir código de trabajo en la menor cantidad de bytes posible en el idioma elegido.

Nota: el ñu queda atrapado (al igual que el caballero en su ubicación de , cuadrado , y el camello en su , cuadrado ) en su ubicación en el cuadrado . El comportamiento de su código puede ser indefinido para más grande que esto. (¡Gracias a Deadcode por el código C ++ que encontró esto!)2016th20843723rd708112899744968th12851850258n

Detalle

El tablero se ve como el siguiente y continúa indefinidamente:

101 100  99  98  97  96  95  94  93  92  91
102  65  64  63  62  61  60  59  58  57  90
103  66  37  36  35  34  33  32  31  56  89
104  67  38  17  16  15  14  13  30  55  88
105  68  39  18   5   4   3  12  29  54  87
106  69  40  19   6   1   2  11  28  53  86
107  70  41  20   7   8   9  10  27  52  85
108  71  42  21  22  23  24  25  26  51  84
109  72  43  44  45  46  47  48  49  50  83
110  73  74  75  76  77  78  79  80  81  82
111 112 113 114 115 116 117 118 119 120 121

Un ñu es una pieza de ajedrez de hadas "gnu" , una pieza de ajedrez no estándar que puede moverse tanto como un caballero (un ) y como un camello (un ). Como tal, podría mudarse a cualquiera de estos lugares desde su ubicación inicial de :(1,2)( 1 , 3 ) 1(1,3)
1

  .   .   .   .   .   .   .   .   .   .   .
  .   .   .   .  35   .  33   .   .   .   .
  .   .   .   .  16   .  14   .   .   .   .
  .   .  39  18   .   .   .  12  29   .   .
  .   .   .   .   .  (1)  .   .   .   .   .
  .   .  41  20   .   .   .  10  27   .   .
  .   .   .   .  22   .  24   .   .   .   .
  .   .   .   .  45   .  47   .   .   .   .
  .   .   .   .   .   .   .   .   .   .   .

El más bajo de estos es y todavía no ha visitado ese cuadrado, por lo que es el segundo término de la secuencia.1010

A continuación, podría pasar de a cualquiera de estos lugares:10

  .   .   .   .   .   .   .   .   .   .   .
  .   .   .   .   .   .  14   .  30   .   .
  .   .   .   .   .   .   3   .  29   .   .
  .   .   .   .   6   1   .   .   .  53  86
  .   .   .   .   .   .   . (10)  .   .   .
  .   .   .   .  22  23   .   .   .  51  84
  .   .   .   .   .   .  47   .  49   .   .
  .   .   .   .   .   .  78   .  80   .   .
  .   .   .   .   .   .   .   .   .   .   .

Sin embargo, ella ya visitó el cuadrado por lo que su tercera ubicación es el cuadrado , el más bajo que aún no ha visitado.13


Los primeros términos del camino del ñu son:100

1, 10, 3, 6, 9, 4, 7, 2, 5, 8, 11, 14, 18, 15, 12, 16, 19, 22, 41, 17, 33, 30, 34, 13, 27, 23, 20, 24, 44, 40, 21, 39, 36, 60, 31, 53, 26, 46, 25, 28, 32, 29, 51, 47, 75, 42, 45, 71, 74, 70, 38, 35, 59, 56, 86, 50, 78, 49, 52, 80, 83, 79, 115, 73, 107, 67, 64, 68, 37, 61, 93, 55, 58, 54, 84, 48, 76, 43, 69, 103, 63, 66, 62, 94, 57, 87, 125, 82, 118, 77, 113, 72, 106, 148, 65, 97, 137, 91, 129, 85

Los primeros saltos son movimientos de caballeros, por lo que los primeros términos coinciden con A316667 .1112


Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Mego

Respuestas:


21

JavaScript (Node.js) ,  191 ... 166  164 bytes

Guardado 2 bytes gracias a @grimy .

Devuelve el º plazo.N

n=>(g=(x,y)=>n--?g(Buffer('QPNP1O?O@242Q3C3').map(m=c=>g[i=4*((x+=c%6-2)*x>(y+=c%7-2)*y?x:y)**2,i-=(x>y||-1)*(i**.5+x+y)]|i>m||(H=x,V=y,m=i))&&H,V,g[m]=1):m+1)(1,2)

Pruébalo en línea! o Ver una versión formateada

¿Cómo?

Índices espirales

Para convertir las coordenadas en el índice espiral , primero calculamos la capa con:(x,y)IL

L=max(|x|,|y|)

Lo que da:

3210+1+2+333333333232222231321112303210123+13211123+23222223+33333333

Luego calculamos la posición en la capa con:P

P={2L+x+yif x>y(2L+x+y)if xy

Lo que da:

3210+1+2+330123456210123471210125803210369+143234710+254567811+36789101112

El índice final viene dado por:I

I=4L2P

NB: La fórmula anterior da una espiral indexada a 0.

En el código JS, en realidad calculamos inmediato con:4L2

i = 4 * (x * x > y * y ? x : y) ** 2

Y luego reste con:P

i -= (x > y || -1) * (i ** 0.5 + x + y)

Movimientos del ñu

Dada la posición actual , los 16 posibles cuadrados objetivo del ñu se prueban en el siguiente orden:(x,y)

321x+1+2+3391128101761213y+1541415+220+331

Los recorremos aplicando 16 pares de valores con signo . Cada par está codificado como un solo carácter ASCII.(dx,dy)

 ID | char. | ASCII code | c%6-2 | c%7-2 | cumulated
----+-------+------------+-------+-------+-----------
  0 |  'Q'  |     81     |   +1  |   +2  |  (+1,+2)
  1 |  'P'  |     80     |    0  |   +1  |  (+1,+3)
  2 |  'N'  |     78     |   -2  |   -1  |  (-1,+2)
  3 |  'P'  |     80     |    0  |   +1  |  (-1,+3)
  4 |  '1'  |     49     |   -1  |   -2  |  (-2,+1)
  5 |  'O'  |     79     |   -1  |    0  |  (-3,+1)
  6 |  '?'  |     63     |   +1  |   -2  |  (-2,-1)
  7 |  'O'  |     79     |   -1  |    0  |  (-3,-1)
  8 |  '@'  |     64     |   +2  |   -1  |  (-1,-2)
  9 |  '2'  |     50     |    0  |   -1  |  (-1,-3)
 10 |  '4'  |     52     |   +2  |   +1  |  (+1,-2)
 11 |  '2'  |     50     |    0  |   -1  |  (+1,-3)
 12 |  'Q'  |     81     |   +1  |   +2  |  (+2,-1)
 13 |  '3'  |     51     |   +1  |    0  |  (+3,-1)
 14 |  'C'  |     67     |   -1  |   +2  |  (+2,+1)
 15 |  '3'  |     51     |   +1  |    0  |  (+3,+1)

Llevamos un registro del valor mínimo encontrado en de las coordenadas de la celda correspondiente en .m(H,V)

Una vez que se ha encontrado al mejor candidato, lo marcamos como visitado al establecer una bandera en el objeto , que también es nuestra función recursiva principal.g

En la primera iteración, comenzamos con e . Esto asegura que la primera celda seleccionada es y que es la primera celda que se marca como visitada.x=1y=2(0,0)


3
¡Tanto golf, no puedo esperar al resumen de cómo funciona toda la magia!
Jonathan Allan

¿Tuviste que usar Bufferpara obligar a cada personaje a ser interpretado como un solo byte?
Jonás

1
@ Jonás Aunque ha quedado en desuso, el Bufferconstructor aún acepta una cadena. Entonces, sí, esta es una forma bastante barata de convertirlo en una lista de bytes, en lugar de hacerlo [..."string"].map(c=>do_something_with(c.charCodeAt())).
Arnauld

1
-2 bytes en la codificación de coordenadas: TIO
Grimmy

@Grimy ¡Bien hecho!
Arnauld

8

Coco , 337 276 bytes

import math
def g((x,y))=
 A=abs(abs(x)-abs(y))+abs(x)+abs(y)
 int(A**2+math.copysign(A+x-y,.5-x-y)+1)
def f():
 p=x,y=0,0;s={p};z=[2,3,1,1]*2
 while 1:yield g(p);p=x,y=min(((a+x,b+y)for a,b in zip((1,1,2,-2,-1,-1,3,-3)*2,z+[-v for v in z])if(a+x,b+y)not in s),key=g);s.add(p)

Devuelve un generador de valores. Probablemente podría jugar más golf. (Especialmente la secuencia de tuplas de diferencia.) Algoritmo espiral tomado de esta respuesta matemática .

Pruébalo en línea!


1
for a,b in (-> for a,b in((tal vez también puedas jugar a la tupla delta de las tuplas)
Jonathan Allan

1
No es necesario qy un zip es más corto para las tuplas: 306 bytes aún pueden ser golfables, por supuesto
Jonathan Allan

1
... ¿qué tal esto para 284? EDITAR ... esto para 278
Jonathan Allan

1
Fwiw, esa respuesta math.se tiene x y y intercambiado y tanto relativa negativa al sistema de coordenadas en este desafío (donde positivo x es correcto y y es hacia arriba). No es que haga ninguna diferencia debido a las simetrías, pero aún así.
Código muerto el

1
0.5-> .5para otro byte guardar; A**2-> A*Apara uno más.
Jonathan Allan

8

05AB1E , 77 65 58 57 52 bytes

Xˆ0UF3D(Ÿ0KãʒÄ1¢}εX+}Dε·nàDtyÆ+yO·<.±*->}D¯KßDˆkèU}¯

-6 bytes gracias a @Arnauld utilizando un puerto de su fórmula.

Emite los primeros valores como una lista (de decimales).n+1

Pruébelo en línea ( ïen el pie de página se elimina .0para hacer que la salida sea más compacta, pero no dude en eliminarla para ver el resultado real).

Explicación del código:

Xˆ             # Put integer 1 in the global_array (global_array is empty by default)
0U             # Set variable `X` to 0 (`X` is 1 by default)
F              # Loop the (implicit) input amount of times:
 3D          #  Push the list in the range [-3,3]: [-3,-2,-1,0,1,2,3]
     0K        #  Remove the 0: [-3,-2,-1,1,2,3]
       ã       #  Cartesian product with itself, creating each possible pair: [[3,3],[3,2],[3,1],[3,-1],[3,-2],[3,-3],[2,3],[2,2],[2,1],[2,-1],[2,-2],[2,-3],[1,3],[1,2],[1,1],[1,-1],[1,-2],[1,-3],[-1,3],[-1,2],[-1,1],[-1,-1],[-1,-2],[-1,-3],[-2,3],[-2,2],[-2,1],[-2,-1],[-2,-2],[-2,-3],[-3,3],[-3,2],[-3,1],[-3,-1],[-3,-2],[-3,-3]]
        ʒ   }  #  Filter this list of pairs by:
         Ä     #   Where the absolute values of the pair
          1¢   #   Contains exactly one 1
               #  (We now have the following pairs left: [[3,1],[3,-1],[2,1],[2,-1],[1,3],[1,2],[1,-2],[1,-3],[-1,3],[-1,2],[-1,-2],[-1,-3],[-2,1],[-2,-1],[-3,1],[-3,-1]])
 εX+}          #  Add the variable `X` (previous coordinate) to each item in the list
 D             #  Duplicate this list of coordinates
  ε            #  Map each `x,y`-coordinate to:
   ·           #   Double both the `x` and `y` in the coordinate
    n          #   Then take the square of each
     à         #   And then pop and push the maximum of the two
   Dt          #   Duplicate this maximum, and take its square-root
     yÆ        #   Calculate `x-y`
       +       #   And add it to the square-root
   yO          #   Calculate `x+y`
     ·         #   Double it
      <        #   Decrease it by 1
             #   And pop and push its signum (-1 if < 0; 0 if 0; 1 if > 0)
   *           #   Multiply these two together
    -          #   And subtract it from the duplicated maximum
   >           #   And finally increase it by 1 to make it 1-based instead of 0-based
  }D           #  After the map: Duplicate that list with values
    ¯K         #  Remove all values that are already present in the global_array
      ß        #  Pop the list of (remaining) values and push the minimum
       Dˆ      #  Duplicate this minimum, and pop and add the copy to the global_array
         k     #  Then get its index in the complete list of values
          è    #  And use that index to get the corresponding coordinate
           U   #  Pop and store this coordinate in variable `X` for the next iteration
             # After the outer loop: push the global_array (which is output implicitly)

Explicación general:

Conservamos todos los resultados (y, por lo tanto, los valores que ya hemos encontrado) en global_array, que inicialmente se inicia como [1].
Mantenemos la actual coordenada en variable , que es inicialmente .x,yX[0,0]

La lista de coordenadas que podemos alcanzar en base a la actual coordenada son:x,y

[[x+3,y+1], [x+3,y-1], [x+2,y+1], [x+2,y-1], [x+1,y+3], [x+1,y+2], [x+1,y-2], [x+1,y-3], [x-1,y+3], [x-1,y+2], [x-1,y-2], [x-1,y-3], [x-2,y+1], [x-2,y-1], [x-3,y+1], [x-3,y-1]]

La lista que menciono en la explicación del código anterior contiene estos valores a los que podemos saltar, después de lo cual se agrega la actual (almacenada en la variable ).x,yX

Luego calculará los valores espirales basados ​​en estas coordenadas . Lo hace mediante el uso de la siguiente fórmula para una determinada coordenada :x,yx,y

T=max((2x)2,(2y)2)
R=T(xy+T)signum((x+y)21)+1

Cuál es la misma fórmula que @Arnauld está usando en su respuesta , pero escrita de manera diferente para hacer uso de las incorporaciones de 05AB1E para doble, cuadrado, -1, +1, etc.

(Si desea ver solo esta parte espiral del código en acción: Pruébelo en línea ).

Después de obtener todos los valores que podemos alcanzar para la coordenada dada, eliminamos todos los valores que ya están presentes en el , y luego obtenemos el mínimo de los valores (restantes). Este mínimo se agrega a , y la variable se reemplaza con la coordenada de este mínimo.x,yx , yglobal_array
global_arrayXx,y

Después de que hayamos enlazado la inputcantidad de veces, el programa generará esto global_arraycomo resultado.


1
FWIW, aquí hay un puerto de mi propia fórmula para convertir las coordenadas en índices espirales. Es 5 bytes más corto pero produce flotantes. (No sé si esto es un problema o no.)
Arnauld

(Tenga en cuenta que en su código es en el mío)- yyy
Arnauld

@Arnauld Gracias, eso ahorra 5 bytes adicionales. :) EDITAR: Que ya mencionaste en tu primer comentario. ; p
Kevin Cruijssen
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.