Caballero Distancia


24

En Ajedrez, un Caballero en la cuadrícula (x, y) puede moverse a (x-2, y-1), (x-2, y + 1), (x-1, y-2), (x-1, y + 2), (x + 1, y-2), (x + 1, y + 2), (x + 2, y-1), (x + 2, y + 1) en un solo paso. Imagine un tablero de ajedrez infinito con solo un Caballero encendido (0, 0):

¿Cuántos pasos se requieren para mover un Caballero de (0, 0) a (t x , t y )?

Entradas

Dos enteros: t x , t y ;

-100 <t x <100, -100 <t y <100

Salida

Pasos mínimos necesarios para mover un Caballero de (0, 0) a (t x , t y ).

Reglas

  • código de golf

Casos de prueba

  x    y -> out
  0,   0 ->  0
  0,   1 ->  3
  0,   2 ->  2
  1,   1 ->  2
  1,   2 ->  1
  3,   3 ->  2
  4,   0 ->  2
 42,  22 -> 22
 84,  73 -> 53
 45,  66 -> 37
 99,  99 -> 66
-45, -91 -> 46
-81,   1 -> 42
 11,  -2 ->  7

document.write('<div>');[..."EFEDEDCDCBCBCBCBCBCBCBCBCBCBCBCBCBCDCDEDEFE;FEDEDCDCBCBABABABABABABABABABABABCBCDCDEDEF;EDEDCDCBCBABABABABABABABABABABABABCBCDCDEDE;DEDCDCBCBABA9A9A9A9A9A9A9A9A9A9ABABCBCDCDED;EDCDCBCBABA9A9A9A9A9A9A9A9A9A9A9ABABCBCDCDE;DCDCBCBABA9A9898989898989898989A9ABABCBCDCD;CDCBCBABA9A989898989898989898989A9ABABCBCDC;DCBCBABA9A98987878787878787878989A9ABABCBCD;CBCBABA9A9898787878787878787878989A9ABABCBC;BCBABA9A989878767676767676767878989A9ABABCB;CBABA9A98987876767676767676767878989A9ABABC;BABA9A9898787676565656565656767878989A9ABAB;CBA9A989878767656565656565656767878989A9ABC;BABA98987876765654545454545656767878989ABAB;CBA9A987876765654545454545456567678789A9ABC;BABA98987676565454343434345456567678989ABAB;CBA9A987876565454343434343454565678789A9ABC;BABA98987676545434323232343454567678989ABAB;CBA9A987876565434323232323434565678789A9ABC;BABA98987676545432341214323454567678989ABAB;CBA9A987876565434321232123434565678789A9ABC;BABA98987676545432323032323454567678989ABAB;CBA9A987876565434321232123434565678789A9ABC;BABA98987676545432341214323454567678989ABAB;CBA9A987876565434323232323434565678789A9ABC;BABA98987676545434323232343454567678989ABAB;CBA9A987876565454343434343454565678789A9ABC;BABA98987676565454343434345456567678989ABAB;CBA9A987876765654545454545456567678789A9ABC;BABA98987876765654545454545656767878989ABAB;CBA9A989878767656565656565656767878989A9ABC;BABA9A9898787676565656565656767878989A9ABAB;CBABA9A98987876767676767676767878989A9ABABC;BCBABA9A989878767676767676767878989A9ABABCB;CBCBABA9A9898787878787878787878989A9ABABCBC;DCBCBABA9A98987878787878787878989A9ABABCBCD;CDCBCBABA9A989898989898989898989A9ABABCBCDC;DCDCBCBABA9A9898989898989898989A9ABABCBCDCD;EDCDCBCBABA9A9A9A9A9A9A9A9A9A9A9ABABCBCDCDE;DEDCDCBCBABA9A9A9A9A9A9A9A9A9A9ABABCBCDCDED;EDEDCDCBCBABABABABABABABABABABABABCBCDCDEDE;FEDEDCDCBCBABABABABABABABABABABABCBCDCDEDEF;EFEDEDCDCBCBCBCBCBCBCBCBCBCBCBCBCBCDCDEDEFE"].forEach(c=>document.write(c==';'?'<br>':`<span class="d-${c}">${c}</span>`));
document.write('<style>body{line-height:16px;color:rgba(255,255,255,0.2);}span{display:inline-block;width:16px;font-size:16px;text-align:center;}div{white-space:pre;}');[...'0123456789ABCDEF'].map((c,i)=>document.write(`.d-${c}{background:hsl(${60-4*i},80%,${65-2*i}%)}`));

OEIS relacionados

Aquí hay algunos OEIS para leer más

  • A018837 : Número de pasos para que el caballero alcance (n, 0) en un tablero de ajedrez infinito.
  • A018838 : Número de pasos para que el caballero alcance (n, n) en el tablero de ajedrez infinito.
  • A065775 : Matriz T leída por diagonales: T (i, j) = número mínimo de movimientos de caballero en un tablero de ajedrez (infinito en todas las direcciones) necesarios para moverse de (0,0) a (i, j).
  • A183041 : Número mínimo de movimientos de caballeros de (0,0) a (n, 1) en el tablero de ajedrez infinito.

Usted puede tomar una referencia de la fórmula dada en oeis.org/A065775
TSH

2
¿Puedo tomar la entrada como un número complejo x+yi?
Lynn

1
@lynn, creo que es aceptable.
tsh

@ user202729 actualizó el fragmento de código para mostrar el resultado.
tsh

Un muy buen mapa.
Willtech

Respuestas:


11

Wolfram Language (Mathematica) , 64 bytes

Usando el incorporado KnightTourGraph.

Guardado 2 bytes gracias a Mathe172 .

GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+4),y+2,(x-2)y-2]&

Pruébalo en línea!

ArrayPlot @ Array [GraphDistance [KnightTourGraph @@ ({x, y} = Abs @ {##} + 5), 2y + 3, (x-2) y-2] &, {65,65}, - 32]


14
Mathematica builtins strike de nuevo
qwr

1
Un poco más corto:GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+5),2y+3,(x-2)y-2]&
Lukas Lang el

¿Qué pasa con este idioma? ¿Cómo es que todos estos elementos integrados están precargados? ¿Tratar de completar una frase con tabulador lleva años?
OganM

@OganM Mathematica no admite la finalización automática en su interfaz de línea de comandos. La finalización automática en la interfaz portátil se parece a esto .
alephalpha

1
@OganM Quizás los desarrolladores usan un Trie (estructura de datos), o simplemente una búsqueda binaria en la lista de elementos integrados ordenados. Sí, ¿por qué la búsqueda lineal? El | Tenga en cuenta que Mathematica es un lenguaje de código cerrado no libre, por lo que nadie sabe cómo funciona realmente el predictor. El | Los programadores reales no necesitan autocompletar. : P
user202729

7

JavaScript (ES6), 90 75 72 bytes

Inspirado en la fórmula dada para A065775 . Lento como el infierno para (no tan) largas distancias.

f=(x,y,z=x|y)=>z<0?f(-y,x):z>1?1+Math.min(f(x-1,y-2),f(x-2,y-1)):z*3^x&y

Pruébalo en línea!

¿Cómo?

Definimos z como el OR bit a bit entre x e y .

Paso 1

Primero nos aseguramos de que estamos ubicados en un cuadrante específico al forzar que x e y no sean negativos. Siempre que z <0 (lo que significa que x o y es negativo), procesamos la llamada recursiva f (-y, x) :

(+1, -2) --> (+2, +1)
(-1, +2) --> (-2, -1) --> (+1, -2) --> (+2, +1)
(-1, -2) --> (+2, -1) --> (+1, +2)

Paso 2

Si bien tenemos z> 1 (lo que significa que x o y es mayor que 1 ), intentamos recursivamente los dos movimientos que nos acercan a (0, 0) : f (x-1, y-2) y f ( x-2, y-1) . Eventualmente mantenemos el camino más corto.

Paso 3

Cuando z es menor o igual a 1 , nos quedan 3 posibilidades que se procesan con z*3^x&y(podríamos usarz*3-x*y en lugar):

  • x & y == 1 implica x | y == 1 y significa que x = y = 1 . Necesitamos dos movimientos más para alcanzar (0, 0) :

    2 movimientos

  • X & Y == 0 y x | y == 1 significa que tenemos x = 1 / y = 0 o x = 0 / y = 1 . Necesitamos tres movimientos más para alcanzar (0, 0) :

    3 movimientos

  • X & Y == 0 y x | y == 0 significa que ya tenemos x = y = 0 .

Gráficos prestados de chess.com


5

Python 3 , 90 bytes

Gracias tsh por -11 bytes!

def f(x,y):x=abs(x);y=abs(y);s=x+y;return(.9+max(x/4,y/4,s/6)-s/2+(s==1or x==y==2))//1*2+s

Pruébalo en línea!

(formato de código en línea para evitar que los lectores tengan que desplazarse. Lo siento, pero tengo que jugar golf en mi programa)

Muy muy eficiente.


¿Cómo podría llegar a esto?

1. paridad

Asume que todo el tablero está coloreado en el patrón de tablero de ajedrez (es decir, las celdas con x+ypares e impares x+yestán coloreadas con diferentes colores).

Tenga en cuenta que cada paso debe saltar entre dos celdas de colores diferentes. Por lo tanto:

  • La paridad del número de pasos debe ser igual a la paridad de x+y.

2. Aproximación

Asume que el caballero comienza desde la coordenada (0,0), y ha movido los npasos, y actualmente está en (x,y).
Para simplificar, se supone x ≥ 0, y ≥ 0.
Podemos concluir:

  • Puesto que cada paso xaumenta como máximo 2, x ≤ 2×n. Del mismo modo, y ≤ 2×n.
  • Puesto que cada paso x+yaumenta como máximo 3, x+y ≤ 3×n.

Por lo tanto, n ≥ l(x,y)donde l(x,y) = max(max(x,y)/2, (x+y)/3. (tenga en cuenta que no necesitamos incluir -xo x-yen la fórmula porque por suposición,, x ≥ 0 and y ≥ 0so x+y ≥ max(x-y,y-x,-x-y)y x ≥ -x, y ≥ -y)

Resulta que a(x,y) = round(0.4 + l(x,y))es una buena aproximación a n.

  • Supongamos que a(x,y)es una aproximación con un error menor que 1, el valor correcto viene dado por

    f(x,y) = round((a(x,y) - (x+y)) / 2) * 2 + (x+y)

    (redondear debajo de restar x+yy dividir por 2)

3. Casos especiales que no cumplen la fórmula.

Asumir x ≥ 0y y ≥ 0. Hay 2 casos especiales donde el algoritmo falla:

  • x == 1 and y == 0o x == 0 and y == 1: El algoritmo regresa incorrectamente 1mientras la respuesta correcta es 3.
  • x == y == 2: El algoritmo regresa incorrectamente 2mientras que la respuesta correcta es 4.

Entonces, solo casos especiales. Agregue el resultado por 2si el valor de xy yes uno de esos.


1
@tsh Pero eso también es cierto x==y==0.
user202729

¿Por qué max(x+y,x-y,y-x)?
tsh

@tsh: No, ver: x = -5, y = 5. x + y = 0, abs (xy) = 10 y por lo tanto x + y <abs (xy)
Nova

@Nova "Asumir x ≥ 0y y ≥ 0".
user202729

4

Python 2 , 87 bytes

f=lambda z,a={0}:1-({z}<=a)and-~f(z,{k+1j**i*(2-i/4*4+1j)for k in a for i in range(8)})

Pruébalo en línea!

Toma la entrada como un número complejo z = complex(tx, ty).


4

TI-Basic, 86 54 bytes

Basado en la solución anterior de @ user202729

Input :abs(X->C:abs(Y->D:C+Ans
Ans+2int(.9+(S=1 or C=2 and D=2)-.5Ans+max({C/4,D/4,Ans/6

2

MATL , 29 bytes

`JEQ2J-htZjht_h@Z^2&sG=~}@Gg*

La entrada es un número complejo con partes enteras reales e imaginarias.

El código es muy ineficiente. Sus requisitos de memoria aumentan exponencialmente con la salida. Se agota el tiempo de espera en TIO para los casos de prueba con una salida superior a 7.

Pruébalo en línea!


2

Haskell, 79 72 bytes

p l|elem(0,0)l=0|r<-[-2..2]=1+p[(x+i,y+j)|(x,y)<-l,i<-r,j<-r,(i*j)^2==4]

Pruébalo en línea!

Toma la entrada como una lista singleton de pares de números.

Una simple fuerza bruta. Necesita mucho tiempo y memoria para los resultados> 8. Comenzando con una lista de coordenadas de un solo elemento (la entrada), agregue repetidamente todas las posiciones que se pueden alcanzar para cada elemento hasta que (0,0)esté en esta lista. Realice un seguimiento del nivel de recursión y devuélvalo como resultado.

Editar: -7 bytes gracias a @Lynn.



1

JavaScript (ES6), 90 78 bytes

f=(x,y)=>y<0?f(x,-y):x<y?f(y,x):x+y<3?4-x-y&3:x-3|y-1?x-4|y-3?f(x-2,y-1)+1:3:2

Editar: Guardado 12 bytes gracias a @supercat señalando que x<0implica y<0o x<y. Explicación: Esta es una solución recursiva. Las dos primeras condiciones solo aseguran el cuadrante correcto para las otras condiciones. La tercera condición genera la respuesta para las coordenadas cerca del origen, mientras que las dos últimas condiciones se refieren a los otros dos casos especiales (1 byte más corto que probar ambos movimientos):

0
32
2++
+2++
+++3+
++++++
(etc.)

Todos los cuadrados marcados +se pueden determinar moviéndose directamente hacia el origen y luego recurriendo.


¿Necesitas la x<0prueba? Dado, por ejemplo, -3,6, la x<yprueba convertiría eso en 6, -3, que la y<0prueba convertiría en 6,3, que la x<yprueba convertiría en 3,6.
supercat

@supercat De hecho, como diría Python, x>=y>=0...
Neil

1

Kotlin , 148 146 140 bytes

fun s(x:Int,y:Int):Int=if(y<0)s(x,-y)else
if(x<y)s(y,x)else if(x+y<3)4-x-y and 3
else if(x!=3||y!=1)if(x!=4||y!=3)s(x-2,y-1)+1
else 3 else 2

Pruébalo en línea!


Estoy bastante seguro de que no necesita :Intespecificar el tipo de retorno.
therealfarfetchd

Las funciones recursivas requieren un tipo de retorno ya que el compilador no es lo suficientemente inteligente como para descubrir el tipo.
JohnWells

1
Oh, perdí las llamadas recursivas. Whoops
therealfarfetchd

1

Jalea , 27 26 25 23 bytes

1,-pḤµ;UÆị
¢ṗS€;0i
0ç1#

Pruébalo en línea!

Muy lento; agota el tiempo de espera en TIO para salidas superiores a 6. Toma un número complejo como entrada.

Explicación

El código usa números complejos porque era más corto en un paso intermedio y también parece mucho más rápido; También puede usar pares quitando Æiy reemplazando 0con 0,0en la segunda línea.

1,-pḤµ;UÆị    Helper link. No arguments.
1,-             Get the pair [1,-1].
    Ḥ           Double each to get [2,-2].
   p            Cartesian product: get [[1,2],[1,-2],[-1,2],[-1,-2]].
     µ          Start a new chain with the list of pairs as argument.
       U        Reverse each pair.
      ;         Append the reversed pairs to the list.
        Æi      Convert each pair [real,imag] to a complex number.

¢ṗS€;0i    Helper link. Arguments: iterations, target
¢            Call the previous link to get knight moves as complex numbers.
 ṗ           Get the iterations-th Cartesian power of the list. This will
             yield 8^n tuples containing move sequences.
  S€         Sum each move sequence to get the resulting square.
    ;0       Add the starting square, since the zeroth iteration results
             in no move sequences.
      i      Find the target squares (1-based) index in the results, or 0.

0ç1#    Main link. Argument: target
0         Starting from 0,
   #      find the
  1       first number of iterations where
 ç        calling the previous link results in a nonzero result.
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.