La mossa più lunga di Dama cinese


12

Nelle pedine cinesi , un pezzo può muoversi saltando su un altro pezzo o eseguendo una sequenza di tali salti. Il tuo compito è trovare la sequenza più lunga possibile di luppolo.

Ingresso

Una sequenza di 121 zero o uno, ognuno dei quali rappresenta un posto su una tavola. Uno zero indica che il posto è vuoto; uno indica che il posto è occupato. Le posizioni sono elencate da sinistra a destra; dall'alto al basso. Ad esempio, l'input di questa configurazione sarebbe

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

Spiegazione:

Il primo posto è occupato da un pezzo verde, quindi la prima cifra nell'input è 1. La seconda fila ha una posizione vuota e poi una posizione occupata, quindi 01viene la prossima. La terza fila è tutta occupata, quindi 111. La quarta fila ha due spazi vuoti e due occupati (andando da sinistra a destra), quindi 0011. Poi arrivano cinque 0, una 1e sette 0per la riga successiva e così via.

Come in quella configurazione, c'è un angolo che punta verso l'alto. Ci può essere un numero qualsiasi di pezzi sul tabellone (da 1 a 121). Si noti che pezzi di colori diversi non sono rappresentati in modo diverso.

Produzione

La lunghezza massima di un hop legale, usando qualsiasi pezzo sul tabellone. Non puoi visitare lo stesso posto più di una volta (comprese le posizioni iniziale e finale). Tuttavia, potresti saltare sullo stesso pezzo più di una volta. Se non esiste un hop legale, output 0. Non considerare se esiste una mossa legale senza hop.

Ad esempio, l'output all'impostazione sopra descritta è 3.

L'input e l'output possono essere eseguiti tramite stdin e stdout, tramite argomenti della riga di comando, tramite chiamate di funzione o qualsiasi metodo simile.

Casi test

Ingresso:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

Uscita: 0(non ci sono due pezzi uno accanto all'altro)


Ingresso:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

Output: 1(impostazione iniziale per un giocatore nell'angolo in alto a sinistra)


Ci gioco con mia prozia; siamo entrambi ragionevolmente bravi. Questa è una sfida interessante.
cjfaure,

1
Forse dovresti specificare di più su come è memorizzato l'input / quali bit vanno dove.
TheDoctor

Quali pezzi puoi "saltare"? Come suonavamo mia madre e io, puoi saltare un singolo pezzo in una delle 6 direzioni a qualsiasi distanza (nel punto opposto del pezzo su cui sei saltato) fintanto che non ci sono pezzi sulla strada del percorso per quel luppolo. Altri giocano che puoi saltare solo su pezzi adiacenti.
Joe Z.,

1
@TheDoctor Ho aggiunto una spiegazione più dettagliata.
Ypnypn,

Puoi chiarire un dettaglio: posso occupare due volte la stessa posizione? Presumo di non poter fare il loop all'infinito, ma se riesco a colpire una posizione muovendola da sinistra a destra e poi colpendola di nuovo spostandola da sinistra a destra verso il basso, allora si aprono possibilità.
Devon Parsons,

Risposte:


1

Perl, 345 322

Modifica: golfato, leggermente.

Altri casi di test sarebbero belli, ma per ora sembra che funzioni. Aggiungerò commenti in seguito, se necessario. Con newline e rientro per la leggibilità:

$_=<>;
$s=2x185;
substr$s,(4,22,unpack'C5(A3)*','(:H[n129148166184202220243262281300')[$i++],0,$_ 
    for unpack A.join A,1..4,13,12,11,10,9..13,4,3,2,1;
$_=$s;
sub f{
    my(@a,%h)=@_;
    $h{$_}++&&return for@a;
    $-+=$#a>$-;
    $s=~/^.{$a[0]}$_/&&f($+[1],@a)
        for map{("(?=.{$_}1.{$_}(0))","(?<=(0).{$_}1.{$_}.)")}0,17,18
}
f$+[0]while/1/g;
print$-

Ho aggiunto un paio di casi di test.
Ypnypn,

Funzionano bene, ma sono troppo facili :-).
user2846289

2

C, 262 260

Codice golfato ( codice di debug e spazio bianco non necessario rimosso. Modificato dall'input tramite stdin per l'input dalla riga di comando e ha approfittato dell'opportunità di dichiarare la variabile i lì. Ultima modifica: il codice è stato spostato tra parentesi di forloop per salvare due punti e virgola.)

t[420],j,l,x,y;f(p,d){int z,q,k;for(k=6;k--;t[q]&!t[p+z]?t[q]=0,f(q,d+1),t[q]=1:0)z="AST?-,"[k]-64,q=p+z*2;l=d>l?d:l;}main(int i,char**s){for(i=840;i--;x>3&y>5&x+y<23|x<13&y<15&x+y>13?i>420?t[i-420]=49-s[1][j++]:t[i]||f(i,0):0)x=i%20,y=i/20%21;printf("%d",l);}

Spiegazione

Questo si basa su una scheda 20x21 che assomiglia a questa, inizialmente riempita di zeri all'avvio del programma (questa arte ASCII è stata generata da una versione modificata del programma e mentre il iciclo conta verso il basso, lo zero si trova nell'angolo in basso a destra):

....................
....................
...............#....
..............##....
.............###....
............####....
.......#############
.......############.
.......###########..
.......##########...
.......#########....
......##########....
.....###########....
....############....
...#############....
.......####.........
.......###..........
.......##...........
.......#............
....................
....................

Il ciclo iattraversa questa scheda due volte, usando xey per calcolare se un quadretto appartiene effettivamente alla scacchiera o meno (ciò richiede 6 disparità separate in xey).

In tal caso, la prima volta che riempie i quadrati, inserisce un 0(falso) per un 1(occupato) e un 1(vero) per un 0(non occupato). Questa inversione è importante, perché tutti i quadrati fuori limite contengono già uno 0, il che significa che assomigliano ai quadrati occupati ed è chiaro che non possono essere saltati, senza la necessità di un controllo specifico.

La seconda volta, se il quadrato è occupato (contiene 0) chiama la funzione fche cerca le mosse.

fcerca ricorsivamente nelle 6 direzioni possibili codificate da +/- 1 (orizzontale), +/- 20 (verticale) e +/- 19 (diagonale) codificate nell'espressione "AST?-,"[k]-64. Quando trova un colpo, imposta quella cella su 0 (occupata) prima di richiamare se stessa in modo ricorsivo, quindi la riporta su 1 (vuota) quando viene restituita la funzione. Il valore della cella deve essere modificato prima della chiamata ricorsiva per impedire il salto nella cella più di una volta.

Codice Ungolfed

char s[999];                           //input string.
t[420],i,j,l,x,y;                      //t=board. i=board counter, j=input counter. l=length of longest hop found so far.

f(p,d){                                //p=position, d= recursion depth.
  //printf("%d,%d ",p,d);              //debug code: uncomment to show the nodes visited.
  int k,z,q;                           //k=counter,z=displacement,q=destination
  for(k=6;k--;)                        //for each direction
    z="AST?-,"[k]-64,                  //z=direction
    q=p+z*2,                           //q=destination cell
    t[q]&!t[p+z]?                      //if destination cell is empty (and not out of bounds) and intervening cell is full
      t[q]=0,f(q,d+1),t[q]=1           //mark destination cell as full, recurse, then mark it as empty again.
      :0;
  l=d>l?d:l;                           //if d exceeds the max recorded recursion depth, update l
}

main(){
  gets(s);                             //get input
  for(i=840;i--;)                      //cycle twice through t
    x=i%20,                            //get x
    y=i/20%21,                         //and y coordinates
    x>3&y>5&x+y<23|x<13&y<15&x+y>13?   //if they are in the bounds of the board
      i>420?
        t[i-420]=49-s[j++]             //first time through the array put 0 for a 1 and a 1 for a 0 ('1'=ASCII49)
        :t[i]||f(i,0)                  //second time, if t[i]=0,call f(). 
       //,puts("")                     //puts() formats debug output to 1 line per in-bounds cell of the board
      :0;
  printf("%d",l);                      //print output
}
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.