Dove può essere il cavaliere in N mosse?


21

Questo è Hole-3 di The Autumn Tournament di APL CodeGolf . Sono l'autore originale del problema e quindi ho permesso di ripubblicarlo qui.


Dato:

  1. un numero di turni (si prega di indicare se nessun movimento è 0, altrimenti supponiamo che si chiami 1) e

  2. un elenco di una o più posizioni iniziali (in qualsiasi forma, ad esempio 0 o 1 coordinate indicizzate o 64 numeri / caratteri consecutivi o A1 – H8 - indicare quale), su una scacchiera 8 per 8,

restituisce (in qualsiasi ordine) l'elenco di posizioni uniche (nello stesso formato dell'input) a cui il / i cavaliere / i può trovarsi dopo il dato numero di turni.

  • Ogni cavaliere deve muoversi ad ogni turno, ma non devi preoccuparti che più cavalieri occupino lo stesso quadrato.

  • Un cavaliere può spostarsi solo nelle posizioni contrassegnate con X rispetto alla sua posizione attuale, contrassegnate con ♞:
    dove un cavaliere può muoversi

Esempi (coordinate 1 indicizzate)

1passare da [[1,1]]: [[2,3],[3,2]]

2si sposta da [[1,1]]: [[1,1],[1,3],[1,5],[2,4],[3,1],[3,5],[4,2],[4,4],[5,1],[5,3]]

1passare da [[1,1],[5,7]]: [[2,3],[3,2],[3,6],[3,8],[4,5],[6,5],[7,6],[7,8]]

2si sposta da [[1,1],[5,7]]: [[1,1],[1,3],[1,5],[1,7],[2,4],[2,6],[2,8],[3,1],[3,3],[3,5],[3,7],[4,2],[4,4],[4,6],[4,8],[5,1],[5,3],[5,5],[5,7],[6,4],[6,6],[6,8],[7,3],[7,7],[8,4],[8,6],[8,8]]

0si sposta da [[3,4]]: [[3,4]]


Gli spazi degli scacchi possono essere immessi ed emessi numerando 0-63 invece di [rango, file]?
Dave,

@Dave Certo, perché no? Basta essere coerenti con l'I / O.
Adám,

8
Giuro di aver letto questo HNQ come "Dove si trova il cavaliere in Ni si muove"
Sidney,

3
Avviso di gioco di parole: la notazione per cavaliere è N.
Giosuè il

Possiamo usare l'indicizzazione basata su 1 sul numero di passaggi? Ad esempio[[1,1]], 2 -> [[2,3],[3,2]]
Zgarb,

Risposte:


11

Wolfram Language (Mathematica) , 45 byte

Perché l'altra soluzione non è corretta (vedi il commento di Martin sotto), quindi decido di pubblicare la mia soluzione:

8~KnightTourGraph~8~AdjacencyList~#&~Nest~##&

Provalo online!

Notazione infografica definitiva ...

Prende 2 input, il primo è un elenco di numeri nel range che [1,64]descrivono le posizioni iniziali del cavaliere, il secondo è il numero di passi.

Questa soluzione si basa sull'estrema praticità delle funzioni integrate di Mathematica:

  • AdjacencyListpuò prendere un elenco di vertici sul lato destro e restituire un elenco di vertici adiacente a uno di quelli, duplicati già rimossi e ordinati .
  • KnightTourGraphè incorporato. Non sorpresa.
  • Nestaccetta gli argomenti in ordine Nest[f, expr, n], che possiamo dividere il ##lato destro come Nest[f, ##].
  • E infine, Mathematica analizza a~b~c~d~ecome (a~b~c)~d~e, quindi non è necessaria alcuna parentesi quadra. Senza notazione e appiattimento ##, sarebbe Nest[AdjacencyList[KnightTourGraph[8, 8], #] &, #, #2]&.

1
Non credo che ci sia qualcosa di sbagliato nel superare una soluzione esistente.
Adám,

1
Funziona con più posizioni di partenza?
Adám,

Sorprendente! Ora devo capire come leggo questo ...
Dave,

Probabilmente sarebbero 17 byte nell'ipotetico linguaggio del golf Mthmca.
Michael Stern,

7

JavaScript (ES7), 99 byte

Formato di input / output: indici quadrati in [0 ... 63] .

f=(a,n)=>n--?f([...Array(64).keys()].filter(p=>!a.every(P=>(p%8-P%8)**2^((p>>3)-(P>>3))**2^5)),n):a

Casi test

Questo frammento include due funzioni di supporto per la traduzione da e verso il formato fornito dall'OP.

Come?

Una mossa da (x, y) a (X, Y) è una mossa valida per il cavaliere se abbiamo:

  • | xX | = 1 e | yY | = 2 o
  • | xX | = 2 e | yY | = 1

Quadrando invece di usare valori assoluti, questo può essere espresso come:

  • (xX) ² = 1 e (yY) ² = 4 , oppure
  • (xX) ² = 4 e (yY) ² = 1

Poiché 1 e 4 sono gli unici quadrati perfetti che danno 5 quando XOR è insieme, abbiamo una mossa cavaliere valida se:

(xX) ² XOR (yY) ² XOR 5 = 0

Applichiamo questa formula a ciascun quadrato p = 8y + x sulla scacchiera e ogni quadrato del cavaliere P = 8Y + X per dedurre i nuovi possibili quadrati del bersaglio del cavaliere e ripetere ripetutamente questo processo n volte.


5

Ottava, 69 byte

function a=f(a,n,b=~a)for k=1:n;a=b&imdilate(a,de2bi(")0#0)"-31));end

Demo online!

L'ingresso / uscita è la configurazione della scheda all'inizio / fine come una matrice binaria 8 * 8.

Spiegazione:

Per i npassaggi ripetere la dilatazione morfologica della tavola con la seguente maschera:

01010
10001
00100
10001
01010

5

Retina , 147 102 byte

.$
$*	
¶
 ¶
{s`((?<=N(....|.{11}|.{13})?.{7})|(?=.{8}(....|.{11}|.{13})?N))\S(?=.*	)
n
Ts`	Nn`_:N`.*¶	

Provalo online! Accetta input come una scheda 8x8 di :s con i cavalieri contrassegnati con Ns, con una cifra per il numero di turni sulla riga successiva (non ha senso avere più di 9 turni, ma se insisti posso supportarlo per un extra byte). Si noti che l'output contiene spazi bianchi aggiuntivi. Modifica: salvato 45 byte grazie a @MartinEnder. Spiegazione: Il primo stadio converte il numero di turni in unario, ma usando i caratteri di tabulazione, in modo che non vengano abbinati successivamente per caso, mentre il secondo stadio aggiunge alcuni spazi a destra della tavola per impedire che le regex si avvolgano il bordo. Il terzo stadio sostituisce tutti gli Ns :che si allontanano da un cavaliere Ncon un npo 'mentre il quarto stadio cancella tutti gli Ns rimanenti , cambia ilnda s a Ns e sottrae 1 dal conteggio delle mosse. Questo si ripete fino a quando il conteggio delle mosse è zero.


Questo è davvero impressionante. Sicuramente non lo strumento giusto per il lavoro!
Adám,

4

Gelatina , 29 byte

+þ1,2Œ!×þ1,-p`¤¤Ẏ¤Ẏ⁼%8$$ÐfQµ¡

Provalo online!

Coordinate indicizzate 0. Quasi certo che questo non è ottimale.

-1 byte grazie a user202729

Spiegazione

+þ1,2Œ!×þ1,-p`¤¤Ẏ¤Ẏ⁼%8$$ÐfQµ¡  Main Link
+þ                             Addition Table (all pairs using + as combining function) with
  1,2Œ!×þ1,-p`¤¤Ẏ¤             All knight moves:
  1,2                          [1, 2]
     Œ!                        All permutations ([1, 2], [2, 1])
       ×þ                      Product Table (all pairs using × as combining function) with
         1,-p`¤                [1, 1], [1, -1], [-1, 1], [-1, -1]
         1,-                   [1, -1]
            p`                 Cartestian Product with itself
               ¤               All knight moves (in a nested array) as a nilad
                Ẏ¤             Tighten (flatten once); all knight moves in a (semi-)flat array
                        Ðf     Keep elements where
                   ⁼%8$$       The element equals itself modulo 8 (discard all elements out of the range)
                          Q    Remove Duplicates
                           µ   Start new monadic chain (essentially, terminates previous chain)
                            ¡  Repeat n times; n is implicitly the second input (right argument)

1
Gelatina indicizzata 0?
Adám,

1
@Adám semplifica il filtraggio: P
HyperNeutrino,

2
Mi aspetto che Jelly sia in grado di farlo in meno di 15 byte, a causa dell'attuale detentore del record in APL lo fa in 24 caratteri.
Adám,

Quando hai> = 3 $, è probabile che tu possa spostarlo sul link precedente e fare nuovamente riferimento con Ç.
user202729

@ user202729 Oh sì, grazie.
HyperNeutrino,

3

05AB1E , 27 25 byte

Grazie a Emigna per aver salvato 2 byte!

Utilizza coordinate 1 indicizzate.

Codice:

F•eĆ•SÍü‚Dí«δ+€`Ùʒ{`9‹*0›

Utilizza 05AB1E codifica . Provalo online!

Spiegazione:

F                          # Do the following <input_1> times..
 •eĆ•SÍ                    #   Push [-1, -2, 1, 2, -1]
       ü‚                  #   Pairwise pairing: [[-1, -2], [-2, 1], [1, 2], [2, -1]]
         D                 #   Duplicate the array
          í                #   Reverse each element
           «               #   Concatenate to the previous array

Questo ci dà il seguente array:

[[-1, -2], [-2, 1], [1, 2], [2, -1], [-2, -1], [1, -2], [2, 1], [-1, 2]]

Quali sono i delta delle mosse del cavaliere.

            δ+             #   Addition vectorized on both sides
              €`           #   Flatten each element
                Ù          #   Uniquify
                 ʒ         #   Keep elements which..
                  {`9‹     #     Has a maximum element smaller than 9
                      *0›  #     And a minimum element larger than 0

È possibile utilizzare •eĆ•SÍü‚invece di Ƶ‡4в2ô<D(«salvare 2 byte.
Emigna,

@Emigna Ahh, è intelligente, grazie!
Adnan,

2

Python 3, 105 byte

p=lambda g,i:i and list(set(p([x+y for x in g for y in[6,10,15,17,-6,-10,-15,-17]if 0<=x+y<64],i-1)))or g

Devono usare un lambda chiamato per la ricorsione. Non sono sicuro che sia squalificante. Passa nelle posizioni iniziali come elenco di numeri quadrati con indice 0. 0 conta come nessuna mossa.


2

Java (OpenJDK 8) , 124 byte

(m,p)->{for(;m-->0;)for(long a=p,i=p=0,j;i<64;i++)for(j=64;j-->0;)p|=(p=i%8-j%8)*p+(p=i/8-j/8)*p==5?(a>>i&1)<<j:0;return p;}

Provalo online!

Formato di input / output

L'ingresso / uscita è rappresentato come bit in un long(64 bit): i bit impostati indicano che un cavallo è presente, i bit non impostati indicano nessun cavallo. Esempio:

// [[0, 0]]
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001L

spiegazioni

(m, p) -> {                          // Lambda. No currying because m and p are modified
 for(;m-->0;)                        // For each move
  for(long a=p,i=p=0,j;i<64;i++)     // Declare variables, move p to a, create a new p and loop on bits of a.
   for(j=64;j-->0;)                  // Loop on bits of p.
    p |=                             // Assign to p a value.
     (p=i%8-j%8)*p+(p=i/8-j/8)*p==5  // If i -> j is a valid horse move, see Arnauld's JavaScript answer for full explanations
      ? (a>>i&1)<<j                  // Assign the presence of the horse (i-th bit of a) to the resulting board (j-th bit of p).
      : 0;                           // Else it's not a valid horse move
 return p;
}

Crediti

  • 19 byte salvati grazie a Nevay!
  • Riutilizzato il (X-x)²+(Y-y)²==5trucco dalla risposta JavaScript di Arnauld
  • 1 byte in più salvato grazie a Nevay nel nuovo algoritmo!
  • Ancora 7 byte salvati grazie a Nevay passando da int[]64 bit long.

1
169 byte:(m,p)->{for(;m-->0;){int i=64,a[]=p,x,y,u[]={1,3,5,9,15,19,21,23};for(p=new int[i];i-->0;)for(int z:u)if((((x=i/8+z/5-2)|(y=i%8+z%5-2))&-8)==0)p[x*8+y]|=a[i];}return p;}
Nevay,

1
-1 byte:(m,p)->{for(int i,j,a[],x;m-->0;)for(a=p,p=new int[i=64];i-->0;)for(j=64;j-->0;)p[j]|=(x=i%8-j%8)*x+(x=i/8-j/8)*x==5?a[i]:0;return p;}
Nevay,

Grazie @Nevay! L'aggiunta di codice per rimuovere parentesi / blocchi è sempre piacevole! ;-)
Olivier Grégoire,

1
-7 byte sostituendo int[]con long:(m,p)->{for(long i,j,a;m-->0;)for(a=p,p=i=0;i<64;i++)for(j=64;j-->0;)p|=(p=i%8-j%8)*p+(p=i/8-j/8)*p==5?(a>>i&1)<<j:0;return p;}
Nevay,

Saluti, non ho nemmeno pensato di farlo! Bel lavoro, @Nevay ;-)
Olivier Grégoire,

2

Gelatina , 29 28 byte

8Rp`
“¦Ʋƈ2’D_2ṡ2+€µẎ
ÇƓ¡f1£Q

Provalo online!

Il numero di giri è attraverso STDIN, e i quadrati sono un argomento.

Questo collega la soluzione Jelly di HyperNeutrino, ma con un approccio diverso.

Ora battendo @HyperNeutrino di 1 byte intero!

Sono richiesti tutti i suggerimenti per eliminare alcuni byte!

Link 1 (La scacchiera)

8Rp`
8R   = The list [1,2,3,4,5,6,7,8]
  p` = cartesian multiplied with itself (this results in the chessboard)

Link 2 (sposta generazione)

“¦Ʋƈ2’D_2ṡ2+€µẎ
“¦Ʋƈ2’          = the number 103414301
      D         = converted into a list of digits
       _2       = subtract two from each element
         ṡ2     = overlapping pairs
           +€   = add to the list of squares
             µ  = Make sure the next part isn't treated as a right argument
              Ẏ = Tighten the list (Reducing the depth by one)

Link 3 (controllo quadrato)

ÇƓ¡f1£Q
ÇƓ¡     = Repeat link #2 the requested amount of times
   f1£  = Remove everything not a member of link #1 (not on the chess board)
      Q = Make sure squares don't appear more than once

1

Buccia , 18 byte

u!¡ṁö`fΠR2ḣ8=5ṁ□z-

Utilizza l'indicizzazione basata su 1 di quadrati e passaggi. Provalo online!

Spiegazione

u!¡ṁö`fΠR2ḣ8=5ṁ□z-  Implicit inputs, say P=[[1,1],[5,7]] and n=2
  ¡                 Iterate on P:
   ṁö               Map the following function, then concatenate:
                     Argument is a pair, say p=[5,7].
          ḣ8         The range [1,2,..,8]
       ΠR2           Repeat twice, take cartesian product: [[1,1],[1,2],..,[8,8]]
     `f              Filter with this predicate:
                      Argument is a pair, say q=[3,8].
                z-    Zip p and q with difference: [-2,1]
              ṁ□      Sum of squares: 5
            =5        Is it 5? Yes, so [3,8] is kept.
 !                  Take n'th step of the iteration.
u                   Remove duplicates, implicitly print.

1

R , 145 183 134 byte

Questo è il risultato dell'eccellente golf di Giuseppe del mio algo iniziale non troppo golfico (vedi commento sotto)

function(x,n){x=x%/%8*24+x%%8
t=c(49,47,26,22)
t=c(t,-t)
for(i in 1:n)x=intersect(v<-outer(1:8,0:7*24,"+"),outer(x,t,"+"))
match(x,v)}

Provalo online!

Input e output sono basati su 1 ... 64. Prende un vettore di posizione usando la notazione 1 ... 64. Mappa su una notazione 1: 576, ovvero una super-scheda composta da nove schede. In questa notazione, ad ogni iterazione, ogni cavaliere dovrebbe essere in grado di spostarsi di +/- 22,26,47,49 Restituire le posizioni future nella notazione 1 ... 64, escluse quelle che cadono dal tabellone centrale. L'esempio TIO mostra il risultato usando una matrice 8x8.


Questo sembra fallire nel primo caso di test (restituisce 4 coordinate invece di 2).
Zgarb,

Grazie per averlo segnalato Zgarb, penso di aver risolto il problema ora
NofP


o 148 byte se invece lo prendi in [0...63]notazione.
Giuseppe,

1
134 byte , [1..64]per input e output. +1, tuttavia, questa è una risposta eccellente.
Giuseppe,
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.