Connect 4: Spot the Fake!


34

La banca è stata fatta a pezzi e tutti i criminali mafiosi locali hanno un alibi insolito: erano a casa a giocare a Connect 4! Al fine di aiutare con l'indagine, ti viene chiesto di scrivere un programma per convalidare tutte le schede Connect 4 che sono state sequestrate al fine di verificare che le posizioni siano effettivamente posizioni di un gioco Connect 4 valido e che non siano state frettolosamente messe insieme non appena la polizia ha bussato alla porta.

Le regole per connettere 4: giocatori Re Y, a turno, rilasciare tessere del loro colore in colonne di una griglia 7x6. Quando un giocatore lascia cadere una tessera nella colonna, cade per occupare la posizione più bassa non riempita in quella colonna. Se un giocatore riesce a ottenere una scala orizzontale, verticale o diagonale di quattro tessere del suo colore sul tabellone, allora vince e il gioco termina immediatamente.

Ad esempio (con l' Ravvio), la seguente è una posizione di Connect 4 impossibile.

| | | | | | | |
| | | | | | | |
| | | | | | | |
| | |R| | | | |
| | |Y| | | | |
|R| |Y| | | | |

Il programma o la funzione deve contenere una scheda Connect 4 e restituirla

  • Un valore falso, che indica che la posizione è impossibile o
  • Una stringa di numeri da 1 a 7, indicando una possibile sequenza di movimenti che portano a tale posizione (le colonne sono numerate 1da 7da sinistra a destra, e quindi la sequenza 112, per esempio, indica una mossa rosso nella colonna 1, seguita da una mossa giallo nella colonna 1, seguito da una mossa rossa nella colonna 2). Se lo desideri, puoi scegliere una numerazione di colonna diversa da 1234567, purché sia ​​specificato nella soluzione. Se si desidera restituire l'elenco in qualche altro formato; per esempio come un array, [2, 4, 3, 1, 1, 3]allora va bene, purché sia ​​facile vedere quali sono le mosse.

Puoi scegliere di leggere il tabellone in qualsiasi formato ragionevole incluso l'uso di lettere diverse da Re Yper i giocatori, ma devi specificare quale giocatore inizia per primo. Puoi presumere che il tabellone sarà sempre 6x7, con due giocatori.

Puoi presumere che le posizioni che ricevi siano almeno fisicamente possibili da creare su una scheda Connect 4 standard; cioè che non ci saranno pezzi "fluttuanti". Puoi presumere che la scheda non sarà vuota.

Questo è il golf del codice, quindi vince la risposta più breve. Si applicano scappatoie standard.

Esempi

| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | --> 1234567 (one possible answer)
| | | | | | | |
|R|Y|R|Y|R|Y|R|

| | | | | | | |
| | | | | | | |
| | | | | | | |
| | |R| | | | | --> false
| | |Y| | | | |
|R| |Y| | | | |

| | | | | | | |
| | |Y| | | | |
| | |R| | | | |
| | |Y| | | | | --> 323333 (only possible answer)
| | |R| | | | |
| |Y|R| | | | |

| | | | | | | |
| | | | | | | |
| | | | | | | |     
| | | | | | | | --> false (this is the position arising after
| |Y|Y|Y|Y| | |     the moves 11223344, but using those moves
| |R|R|R|R| | |     the game would have ended once R made a 4)

| | | | | | | |
| | | | | | | |
|Y| | | | | | |     
|R|Y| | | | | | --> 2134231211 (among other possibilities)
|R|R|Y| | | | |
|Y|R|R|Y| | | |

| | | | | | | |
| | | | | | | |
|Y| | | | | | |     
|R|Y| | | | | | --> false (for example, 21342312117 does not
|R|R|Y| | | | |     work, because Y has already made a diagonal 4)
|Y|R|R|Y| | |R|

| | | | | | | |
| | | | | | | |
| | | | | | | |     
| | | | | | | | --> 112244553 or similar
|Y|Y| |Y|Y| | |
|R|R|R|R|R| | |

John, per curiosità, sai se esiste un algoritmo senza forza bruta?
Giona

Risposte:


9

Gelatina , 57 byte

ŒṪŒ!µ0ịŒṬ¬a³ZU,Ɗ;ŒD$€Ẏṡ€4Ḅo1%15;Ḋ€ṢṚ$Ƒƙ$Ȧȧœị³$2R¤ṁ$ƑµƇṪṪ€

Prende una matrice in cui 0non viene riempito, 1giocato per primo e 2giocato per secondo. Produce un elenco di colonne con 1 indice, vuoto se è stato identificato un falso.

Provalo online! (troppo inefficiente per l'esecuzione di oltre 7 pezzi in meno di un minuto)

Nota:

  1. Presuppone che non siano presenti pezzi "mobili" (risolvilo anteponendo ZṠṢ€Ƒȧ+6 byte)
  2. Suppone che la scheda vuota sia un falso

11

JavaScript (ES6),  202 194 187  183 byte

240

m=>(p=[...'5555555'],g=(c,s=o='')=>/2|4/.test(m)?['',0,2,4].some(n=>m.join``.match(`(1|3)(.{1${n}}\\1){3}`))?o:p.map((y,x)=>m[m[y][x]--^c||p[g(c^6,s+x,p[x]--),x]++,y][x]++)&&o:o=s)(2)

Provalo online!

Come?

g2413 '.

Mentre lo fa, si assicura che non abbiamo alcuna corsa di quattro valori dispari consecutivi fino a quando tutti i valori pari non sono scomparsi (cioè se una parte vince, deve essere l'ultima mossa).

yxp[x] .

Commentate

m => (                            // m[] = input matrix
  p = [...'5555555'],             // p[] = next row for each column
  g = (c,                         // g = recursive function taking c = color,
          s = o = '') =>          //     s = current solution, o = final output
    /2|4/.test(m) ?               // if the matrix still contains at least a 2 or a 4:
      ['', 0, 2, 4]               //   see if we have four consecutive 1's or 3's
      .some(n =>                  //   by testing the four possible directions
        m.join``                  //   on the joined matrix, using
        .match(                   //   a regular expression where the number of characters
          `(1|3)(.{1${n}}\\1){3}` //   between each occurrence is either 1, 10, 12 or 14
        )                         //   (horizontal, diagonal, vertical, anti-diagonal)
      ) ?                         //   if we have a match:
        o                         //     abort and just return the current value of o
      :                           //   else:
        p.map((y, x) =>           //     for each cell at (x, y = p[x]):
          m[                      // 
            m[y][x]--             //       decrement the value of the cell
            ^ c ||                //       compare the original value with c
            p[                    //       if they're equal:
              g(                  //         do a recursive call with:
                c ^ 6,            //           the other color
                s + x,            //           the updated solution
                p[x]--            //           the updated row for this column
              ),                  //         end of recursive call
              x                   //         then:
            ]++,                  //         restore p[x]
            y                     //         and restore m[y][x]
          ][x]++                  //         to their initial values
        ) && o                    //     end of map(); yield o
    :                             // else:
      o = s                       //   we've found a solution: copy s to o
)(2)                              // initial call to g() with c = 2

Nota ho chiesto "Possiamo supporre che la scheda vuota non verrà fornita come input?" - se dobbiamo gestirlo, il tuo codice avrà bisogno di una modifica.
Jonathan Allan, il

non so perché, f([ [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,2,0,2,0,0], [0,2,2,0,2,2,0], [1,1,1,1,1,1,1] ])termina 0 e f([ [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,2,0,2,0,0], [2,2,2,0,2,2,1], [1,1,1,1,1,1,1] ])dovrebbe essere vero
Nahuel Fouilleul,

@NahuelFouilleul Grazie per aver segnalato questo. Ho corretto il codice aggiunto aggiunto questi casi di test.
Arnauld

2

Python 2 , 295 285 byte

def f(a):
 if 1-any(a):return[]
 p=sum(map(len,a))%2
 for i in R(7):
	if a[i][-1:]==`p`:
	 b=a[:];b[i]=b[i][:-1];L=f(b)
	 if L>1>(`1-p`*4in','.join([J((u[j]+' '*14)[n-j]for j in R(7))for n in R(12)for u in[b,b[::-1]]]+b+map(J,zip(*[r+' '*7for r in b])))):return L+[i]
R=range;J=''.join

Provalo online!

-10 grazie a Jo King .

L'input è un elenco di stringhe che rappresentano le colonne; con '1' per il rosso e '0' per il giallo. Le stringhe non sono '' imbottite. Quindi il caso (falso):

| | | | | | | |
| | | | | | | |
|Y| | | | | | |
|R|Y| | | | | |
|R|R|Y| | | | |
|Y|R|R|Y| | |R|

è inserito come:

[
  '0110',
  '110',
  '10',
  '0',
  '',
  '',
  '1'
]

L'output è un elenco di indici di colonna, indicizzati 0, che potrebbero rendere la scheda; o Nonese non è valido.

Accetta la scheda vuota come valida (restituisce l'elenco vuoto []anziché None).

Questo approccio è ricorsivo dall'ultima mossa alla prima mossa: in base alla parità del numero totale di mosse eseguite, rimuoviamo l'ultima mossa rossa o l'ultima mossa gialla (o falliamo se ciò non è possibile); controlla il tabellone risultante per vedere se l'avversario ha 4 di fila (nel qual caso fallire, perché il gioco dovrebbe già essersi fermato); in caso contrario, ricorrere fino a quando la scheda è vuota (che è valida).

Il codice 4 di fila è la parte più gonfia. Tutte le stringhe diagonali per la matrice bsono generate da:

[
    ''.join(
        (u[j]+' '*14)[n-j] for j in range(7)
    )
    for u in[b,b[::-1]]for n in range(12) 
]

che elenca prima le diagonali "inclinate verso il basso" e poi quelle "inclinate verso l'alto".

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.