Knight Distance


24

Negli scacchi, un cavaliere sulla griglia (x, y) può spostarsi su (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) in un solo passaggio. Immagina una scacchiera infinita con solo un Cavaliere su (0, 0):

Quanti passaggi sono necessari per spostare un cavaliere da (0, 0) a (t x , t y )?

ingressi

Due numeri interi: t x , t y ;

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

Produzione

Passaggi minimi necessari per spostare un cavaliere da (0, 0) a (t x , t y ).

Regole

  • codice golf

Casi test

  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 correlato

Ecco alcuni OEIS per ulteriori letture

  • A018837 : Numero di passi che il cavaliere deve raggiungere (n, 0) su una scacchiera infinita.
  • A018838 : Numero di passi che il cavaliere deve raggiungere (n, n) sulla scacchiera infinita.
  • A065775 : Matrice T letta per diagonali: T (i, j) = numero minimo di mosse del cavaliere su una scacchiera (infinita in tutte le direzioni) necessarie per spostarsi da (0,0) a (i, j).
  • A183041 : Minimo numero di mosse del cavaliere da (0,0) a (n, 1) sulla scacchiera infinita.

Puoi prendere un riferimento alla formula data in oeis.org/A065775
tsh

2
Posso prendere input come numero complesso x+yi?
Lynn,

1
@lynn penso sia accettabile.
martedì

@ user202729 ha aggiornato lo snippet di codice per mostrare il risultato.
tsh

Una mappa molto bella.
Willtech,

Risposte:


11

Wolfram Language (Mathematica) , 64 byte

Utilizzando il built-in KnightTourGraph.

Salvato 2 byte grazie a Mathe172 .

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

Provalo online!

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


14
I builtin di Mathematica colpiscono ancora
qwr

1
Leggermente più corto:GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+5),2y+3,(x-2)y-2]&
Lukas Lang,

Che cos'è questa lingua? Come mai tutti questi built-in sono precaricati? Il tentativo di completare una frase con tab richiede secoli?
OganM

@OganM Mathematica non supporta il completamento automatico nell'interfaccia della riga di comando. Il completamento automatico nell'interfaccia notebook si presenta come questo .
alephalpha

1
@OganM Forse gli sviluppatori usano un Trie (struttura dati), o semplicemente una ricerca binaria nell'elenco dei built-in ordinati. Sì, perché la ricerca lineare? | Nota che Mathematica è un linguaggio di origine chiusa non libero, quindi nessuno sa come funziona realmente il predittore. | I veri programmatori non hanno bisogno del completamento automatico. : P
user202729,

7

JavaScript (ES6), 90 75 72 byte

Ispirato alla formula indicata per A065775 . Lento da morire per (non così) lunghe distanze.

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

Provalo online!

Come?

Definiamo z come OR bit a bit tra x ed y .

Passo 1

Per prima cosa ci assicuriamo di trovarci in un quadrante specifico forzando sia x che y ad essere non negativi. Finché z <0 (il che significa che x o y è negativo), elaboriamo la chiamata ricorsiva f (-y, x) :

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

Passo 2

Mentre abbiamo z> 1 (il che significa che x o y è maggiore di 1 ), proviamo in modo ricorsivo le due mosse che ci avvicinano a (0, 0) : f (x-1, y-2) e f ( x-2, y-1) . Alla fine manteniamo il percorso più breve.

Passaggio n. 3

Quando z è minore o uguale a 1 , ci rimangono 3 possibilità che vengono elaborate z*3^x&y(potremmo z*3-x*yinvece usare ):

  • x & y == 1 implica x | y == 1 e significa che x = y = 1 . Abbiamo bisogno di altre due mosse per raggiungere (0, 0) :

    2 mosse

  • x & y == 0 e x | y == 1 significa che abbiamo x = 1 / y = 0 o x = 0 / y = 1 . Abbiamo bisogno di altre tre mosse per raggiungere (0, 0) :

    3 mosse

  • x & y == 0 e x | y == 0 significa che abbiamo già x = y = 0 .

Grafica presa in prestito da chess.com


5

Python 3 , 90 byte

Grazie tsh per -11 byte!

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

Provalo online!

(formattazione del codice in linea per evitare che i lettori debbano scorrere. Mi dispiace, ma devo golf il mio programma)

Molto molto efficiente.


Come potrei venire con questo !?

1. Parità

Presuppone che l'intera scacchiera sia colorata nel motivo a scacchiera (ovvero, le celle con x+ypari e dispari x+ysono colorate con colori diversi).

Si noti che ogni passaggio deve saltare tra due celle di colore diverso. Perciò:

  • La parità del numero di passaggi deve essere uguale alla parità di x+y.

2. Approssimazione

Suppone che il cavaliere inizi dalle coordinate (0,0), abbia spostato i npassi ed è attualmente a (x,y).
Per semplicità, si assume x ≥ 0, y ≥ 0.
Possiamo concludere:

  • Poiché ogni passo xaumenta al massimo di 2, x ≤ 2×n. Analogamente, y ≤ 2×n.
  • Poiché ogni passo x+yaumenta al massimo di 3, x+y ≤ 3×n.

Pertanto, n ≥ l(x,y)dove l(x,y) = max(max(x,y)/2, (x+y)/3. (nota che non abbiamo bisogno di includere -xo x-ynella formula perché per ipotesi,, x ≥ 0 and y ≥ 0quindi x+y ≥ max(x-y,y-x,-x-y)e x ≥ -x, y ≥ -y)

Si scopre che a(x,y) = round(0.4 + l(x,y))è una buona approssimazione a n.

  • Supponiamo che a(x,y)l'approssimazione sia inferiore a 1, il valore corretto è dato da

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

    (round sotto sottrazione x+ye divisione per 2)

3. Casi speciali che falliscono la formula

Assumi x ≥ 0e y ≥ 0. Esistono 2 casi speciali in cui l'algoritmo fallisce:

  • x == 1 and y == 0oppure x == 0 and y == 1: l'algoritmo restituisce in modo errato 1mentre è la risposta corretta 3.
  • x == y == 2: L'algoritmo restituisce in modo errato 2mentre è la risposta corretta 4.

Quindi, solo casi speciali quelli. Aggiungi il risultato 2se il valore di xe ysono uno di quelli.


1
@tsh Ma anche questo è vero x==y==0.
user202729,

Perché max(x+y,x-y,y-x)?
TSH

@tsh: No, vedi: x = -5, y = 5. x + y = 0, abs (xy) = 10 e quindi x + y <abs (xy)
Nova

@Nova "Assumi x ≥ 0e y ≥ 0".
user202729

4

Python 2 , 87 byte

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

Provalo online!

Accetta input come numero complesso z = complex(tx, ty).


4

TI-Basic, 86 54 byte

Basato sulla soluzione precedente di @ 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 byte

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

L'input è un numero complesso con parti intere reali e immaginarie.

Il codice è molto inefficiente. I suoi requisiti di memoria aumentano in modo esponenziale con l'output. Timeout in TIO per i casi di test con output superiore a 7.

Provalo online!


2

Haskell, 79 72 byte

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]

Provalo online!

Prende l'input come un elenco singleton di coppie di numeri.

Una semplice forza bruta. Richiede molto tempo e memoria per i risultati> 8. Partendo da un singolo elenco di coordinate (l'input), aggiungi ripetutamente tutte le posizioni che possono essere raggiunte per ogni elemento fino (0,0)a quando non è in questo elenco. Tieni traccia del livello di ricorsione e restituiscilo come risultato.

Modifica: -7 byte grazie a @Lynn.



1

JavaScript (ES6), 90 78 byte

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

Modifica: salvato 12 byte grazie a @supercat sottolineando che x<0implica y<0o x<y. Spiegazione: questa è una soluzione ricorsiva. Le prime due condizioni garantiscono solo il quadrante giusto per le altre condizioni. La terza condizione genera la risposta per le coordinate vicino all'origine, mentre le ultime due condizioni si occupano degli altri due casi speciali (1 byte più corto del test di entrambe le mosse):

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

Tutti i quadrati contrassegnati +possono essere determinati spostandosi direttamente verso l'origine e quindi ricorrendo.


Hai bisogno del x<0test? Dato ad esempio -3,6, il x<ytest lo trasformerebbe in 6, -3, che il y<0test trasformerebbe in 6,3, che il x<ytest trasformerebbe in 3,6.
supercat

@supercat In effetti, come direbbe Python, x>=y>=0...
Neil,

1

Kotlin , 148 146 140 byte

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

Provalo online!


Abbastanza sicuro di non aver bisogno :Intdi specificare il tipo di ritorno.
therealfarfetchd,

Le funzioni ricorsive richiedono il tipo restituito poiché il compilatore non è abbastanza intelligente da capire il tipo.
JohnWells,

1
Oh, ho perso le chiamate ricorsive. Whoops
therealfarfetchd

1

Gelatina , 27 26 25 23 byte

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

Provalo online!

Molto lento; timeout su TIO per output oltre 6. Accetta un numero complesso come input.

Spiegazione

Il codice utilizza numeri complessi perché era più breve in un passaggio intermedio e sembra anche molto più veloce; puoi anche usare le coppie rimuovendole Æie sostituendole 0con 0,0sulla seconda riga.

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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.