Determina il vincitore Tic-Tac-Toe (a base rotonda)


26

Giochiamo a un po 'di golf!

La sfida è trovare il vincitore di una partita di Tic-Tac-Toe.

Questo è stato fatto molte volte dando una tavola che ha un chiaro vincitore, ma ecco la svolta:

Le celle sono numerate in questo modo:

1|2|3
-+-+-
4|5|6
-+-+-
7|8|9

Ottieni una matrice di esattamente 9 mosse come questa:

{3, 5, 6, 7, 9, 8, 1, 2, 3}

Questo viene analizzato come segue:

  • Il giocatore 1 segna la cella 3
  • Il giocatore 2 segna la cella 5
  • Il giocatore 1 segna la cella 6
  • Il giocatore 2 segna la cella 7
  • Il giocatore 1 segna la cella 9
  • Il giocatore 1 ha vinto

Nota: il gioco non si ferma dopo che un giocatore ha vinto, può succedere che il giocatore perdente riesca a ottenere tre di fila dopo il giocatore vincitore, ma conta solo la prima vittoria.

Il tuo compito ora è ottenere 9 numeri come input e output del giocatore vincitore e del round in cui è avvenuta la vittoria. Se nessuno vince, genera qualcosa di costante a tua scelta. È possibile ricevere input e fornire output attraverso qualsiasi media / formato standard.

Divertiti!

Alcuni altri esempi come richiesto:

{2,3,4,5,6,7,1,8,9} => Player 2 wins in round 6
{1,2,4,5,6,7,3,8,9} => Player 2 wins in round 8
{1,2,3,5,4,7,6,8,9} => Player 2 wins in round 8

11
Benvenuti in PPCG! Questo è un bel primo post, ma di solito non ci piacciono i formati di input / output molto restrittivi . Considereresti di rimuovere "Il giocatore X vince al round Y" e ci lasceresti in un formato ragionevole, come un elenco [X, Y]? In caso di pareggio, possiamo invece generare altri valori coerenti? Lo consiglio vivamente, perché stampare quelle stringhe esatte non fa davvero parte del golf. Per idee di sfida future, ti consiglio di usare il sandbox . :-)
Mr. Xcoder

Scusa colpa mia. Penso che sia corretto ora.
Grunzwanzling,

Leggi la sfida fino alla fine, dico che potrebbe esserci un pareggio e che puoi ottenere qualcosa di tua scelta quando succede. Restituisco {2,6} quando il giocatore 2 vince al turno 6 e {0,0} quando nessuno vince.
Grunzwanzling

Possiamo usare tutto indicizzato 0? (celle, giocatori, round)
Arnauld

1
"Ottieni un array di esattamente 9 mosse del genere: {3, 5, 6, 7, 9, 8, 1, 2, 3}" - dovrebbe 3davvero apparire due volte?
Jonathan Allan,

Risposte:


8

Retina , 114 byte

(.)(.)
$1O$2X
^
123;;456;;789¶X
{`(.)(.*¶)(.)\1
$3$2
}`.*(.)(.)*\1(?<-2>.)*(?(2)(?!))\1.*¶(..)*
$1$#3
.*¶
T
T`d`Rd

Provalo online! Sulla base della mia risposta a Tic-Tac-Toe - X o O? . Emette X<N>se il primo giocatore vince dopo i Nturni, O<N>se il secondo giocatore vince, Tse nessuno dei due vince. Spiegazione:

(.)(.)
$1O$2X
^
123;;456;;789¶X

Crea una tavola interna e segna anche ogni mossa con il giocatore di cui è mossa.

{`(.)(.*¶)(.)\1
$3$2

Applica una mossa.

}`.*(.)(.)*\1(?<-2>.)*(?(2)(?!))\1.*¶(..)*
$1$#3

Cerca una vittoria, e se ne viene trovata una, sostituisci la scheda con il vincitore e il numero di mosse rimanenti.

.*¶
T

Se le mosse sono esaurite e nessuno ha vinto, il gioco è in pareggio.

T`d`Rd

Calcola il numero del round dal numero di mosse rimanenti.


4
Questa è una delle risposte più ... voluttuose che ho visto qui.
Lord Farquaad,

6

MATL , 39 byte

3:g&+XIx"IX@oXK@(XIt!yXdyPXd&hK=Aa?KX@.

L'output è

  • 1e R, in linee separate, se l'utente 1 vince nel round R ;
  • 0e R, in linee separate, se l'utente 2 vince nel round R ;
  • vuoto se nessuno vince.

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

3:       % Push [1 2 3]
g        % Convert to logical. Gives [true true true]
&+       % Matrix of all pairs of additions. Gives a 3×3 matrix, which represents
         % the board in its initial state, namely all cells contain 2. This value
         % means "cell not used yet". 1 will represent "cell marked by user 1",
         % and 0 will represent "cell marked by user 2"
XI       % Copy into clipboard I
x        % Delete
"        % Implicit input: array with moves. For each move
  I      %   Push current board state
  X@     %   Push iteration index (starting at 1), that is, current round number
  o      %   Modulo 2: gives 1 or 0. This represents the current user
  XK     %   Copy into clipboard K
  @      %   Push current move ((that is, cell index)
  (      %   Write user identifier (1 or 0) into that cell. Cells are indexed
         %   linearly in column-major order. So the board is transposed compared
         %   to that in the challenge, but that is unimportant
  XI     %   Copy updated board into clipboard I
  t!     %   Duplicate and transpose
  y      %   Duplicate from below: push copy of board
  Xd     %   Extract main diagonal as a 3×1 vector
  y      %   Duplicate from below: push copy of transposed board
  PXd    %   Flip vertically and extract main diagonal. This is the anti-diagonal
         %   of the board
  &h     %   Concatenate stack horizontally. This concatenates the board (3×3),
         %   transposed board (3×3), main diagonal (3×1 vector) and anti-diagonal
         %   (3×1) into an 3×8 matrix
  K=     %   Push current user identifier. Test for equality with each entry of the
         %   3×8 matrix
  A      %   For each column, this gives true if all its entries are true. Note 
         %   that the first three columns in the 3×8 matrix are the board columns;
         %   the next three are the board rows; and the last two columns are the
         %   main diagonal and anti-diagonal. The result is a 1×8 vector
  a      %   True if any entry is true, meaning the current user has won
  ?      %   If true
    K    %     Push current user identifier
    X@   %     Push current round number
    .    %     Break for loop
         %   Implicit end
         % Implicit end
         % Implicit display

5

Javascript (ES6), 130 byte

m=>m.reduce((l,n,i)=>l||(b[n-1]=p=i%2+1,"012,345,678,036,147,258,048,246".replace(/\d/g,m=>b[m]).match(""+p+p+p)&&[p,i+1]),0,b=[])

f=m=>m.reduce((l,n,i)=>l||(b[n-1]=p=i%2+1,"012,345,678,036,147,258,048,246".replace(/\d/g,m=>b[m]).match(""+p+p+p)&&[p,i+1]),0,b=[])
console.log(JSON.stringify(f([3,5,6,7,9,8,1,2,3])))
console.log(JSON.stringify(f([2,3,4,5,6,7,1,8,9])))
console.log(JSON.stringify(f([1,2,4,5,6,7,3,8,9])))
console.log(JSON.stringify(f([1,2,3,5,4,7,6,8,9])))

Spiegazione

m=>m.reduce((l,n,i)=>               // Reduce the input array with n as the current move
  l||(                              //  If there is already a winner, return it
  b[n-1]=p=i%2+1,                   //  Set the cell at b[n-1] to the current player p
  "012,345,678,036,147,258,048,246" //  For every digit in the list of possible rows:
    .replace(/\d/g,m=>b[m])         //   Replace it with the player at the cell
    .match(""+p+p+p)                //  If any of the rows is filled with p:
      &&[p,i+1]                     //   Return [p, current move]
),0,b=[])

Ti dispiacerebbe fornire una spiegazione o una versione non golfata per favore? Sono interessato a capire la tua soluzione.
Jack

4

Java (OpenJDK 8) , 445 byte

int[] t(int[]m){int[][]f=new int[3][3];boolean z=false;for(int i=0;i<9;i++){f[m[i]%3][m[i]/3]=z?2:1;if(f[m[i]%3][0]==(z?2:1)&&f[m[i]%3][1]==(z?2:1)&&f[m[i]%3][2]==(z?2:1)||f[0][m[i]/3]==(z?2:1)&&f[1][m[i]/3]==(z?2:1)&&f[2][m[i]/3]==(z?2:1)||m[i]%3+m[i]/3==2&&f[0][2]==(z?2:1)&&f[1][1]==(z?2:1)&&f[2][0]==(z?2:1)||m[i]%3==m[i]/3&&f[0][0]==(z?2:1)&&f[1][1]==(z?2:1)&&f[2][2]==(z?2:1)){return(new int[]{(z?2:1),++i});}z=!z;}return(new int[]{0,0});}

Provalo online!

Il valore di ritorno {1,8} indica che il giocatore 1 ha vinto al turno 8. Il valore di ritorno {0,0} significa pareggio.


5
A meno che non si rimuova tutta la spaziatura non necessaria, questa risposta è considerata non valida a causa della mancanza di sforzo di golf. Inoltre, non è consigliabile rispondere alla tua sfida così velocemente e potresti voler aggiungere un link TIO in modo che possiamo testare il tuo codice.
Mr. Xcoder


Mi dispiace, ho copiato la cosa sbagliata. In realtà è molto più breve
Grunzwanzling del

Puoi vedere i suggerimenti per giocare a golf nella domanda Java per rimuovere alcuni byte. Ad esempio falsepuò essere sostituito da 1<0e lo spazio dopo il primo ]può essere rimosso.
user202729

442 byte . Anche il motivo per cui la sezione "Intestazione" e "Piè di pagina" esiste su TIO è che non è necessario commentare //Code that was submittede //End of code.
user202729

2

Kotlin , 236 byte

i.foldIndexed(l()to l()){o,(a,b),p->fun f(i:(Int)->Int)=b.groupBy(i).any{(_,v)->v.size>2}
if(f{(it-1)/3}|| f{it%3}|| listOf(l(1,5,9),l(3,5,7)).any{b.containsAll(it)}){return p%2+1 to o}
b to a+p}.let{null}
fun l(vararg l:Int)=l.toList()

Abbellire

    i.foldIndexed(l() to l()) { o, (a, b), p ->
        fun f(i: (Int) -> Int) = b.groupBy(i).any { (_, v) -> v.size > 2 }
        if (f { (it - 1) / 3 } || f { it % 3 } || listOf(l(1, 5, 9), l(3, 5, 7)).any { b.containsAll(it) }) {
            return p % 2 + 1 to o
        }
        b to a + p
    }.let { null }
fun l(vararg l:Int)= l.toList()

Test

fun f(i: List<Int>): Pair<Int, Int>? =
i.foldIndexed(l()to l()){o,(a,b),p->fun f(i:(Int)->Int)=b.groupBy(i).any{(_,v)->v.size>2}
if(f{(it-1)/3}|| f{it%3}|| listOf(l(1,5,9),l(3,5,7)).any{b.containsAll(it)}){return p%2+1 to o}
b to a+p}.let{null}
fun l(vararg l:Int)=l.toList()

data class Test(val moves: List<Int>, val winner: Int, val move: Int)

val tests = listOf(
        Test(listOf(3, 5, 6, 7, 9, 8, 1, 2, 3), 1, 5),
        Test(listOf(2, 3, 4, 5, 6, 7, 1, 8, 9), 2, 6),
        Test(listOf(1, 2, 4, 5, 6, 7, 3, 8, 9), 2, 8),
        Test(listOf(1, 2, 3, 5, 4, 7, 6, 8, 9), 2, 8)
)

fun main(args: Array<String>) {
    tests.forEach { (input, winner, move) ->
        val result = f(input)
        if (result != winner to move) {
            throw AssertionError("$input ${winner to move} $result")
        }
    }
}

TIO

TryItOnline


1

Python 2 , 170 byte

q=map(input().index,range(1,10))
z=zip(*[iter(q)]*3)
o='',
for l in[q[2:7:2],q[::4]]+z+zip(*z):
 r=[n%2for n in l];y=all(r)*2+1-any(r)
 if y:o+=[max(l)+1,y],
print min(o)

Provalo online! oppure Prova tutti i casi di test

#swap cell number / turn
q=map(input().index,range(1,10))
#split in 3 parts (rows)
z=zip(*[iter(q)]*3)
#starting value for the list with the results
#since string are "greater" than lists, this will
#be the output value when there is a draw
o='',
#iterate over diagonals, rows and columns
for l in[q[2:7:2],q[::4]]+z+zip(*z):
 #use %2 to separate between player 1 and 2
 r=[n%2 for n in l]
 #store in y the value of the player if the trio is a valid win, 0 otherwise
 #it's a win if all moves are from the same player
 y=all(r)*2+1-any(r)
 #if y has a valid player, add the highest turn of the trio, and the player to o
 if y:o+=[max(l)+1,y],
#output the smaller turn of the valid winning trios
print min(o)


1

Python 3.6+, 137 byte

n=m=c=z=0
for a in input():m+=1<<~-int(a);c+=1;z=z or f'{c&1}:{c}'*any(m&t==t for t in[7,56,448,73,146,292,273,84]);n,m=m,n
print(z or-1)

Il formato di output è winner number:roundo -1per un pareggio. Il giocatore 2 è il 0giocatore 1 1. Immettere sotto forma di una stringa non eliminata di numeri quadrati 1 indicizzati.


1

Gelatina , 35 byte

9s3,ZU$$;ŒD$€Ẏf€⁸L€3e
s2ZÇƤ€ZFTḢ;Ḃ$

Un collegamento monadico che prende un elenco delle mosse e restituisce un elenco, in [move, player]cui i giocatori sono identificati come 1(il primo ad agire) e 0(il secondo ad agire).

Provalo online!

Come?

9s3,ZU$$;ŒD$€Ẏf€⁸L€3e - Link 1: any winning play?: list of player's moves:
9s3                   - (range of) nine split into threes = [[1,2,3],[4,5,6],[7,8,9]]
       $              - last two links as a monad:
      $               -   last two links as a monad:
    Z                 -     transpose = [[1,4,7],[2,5,8],[3,6,9]]
     U                -     upend     = [[7,4,1],[8,5,2],[9,6,3]]
   ,                  -  pair = [[[1,2,3],[4,5,6],[7,8,9]],[[7,4,1],[8,5,2],[9,6,3]]]
           $€         - last two links as a monad for €ach:
         ŒD           -   diagonals = [[1,5,9],[2,6],[3],[7],[4,8]] or [[7,5,3],[4,2],[1],[9],[8,6]]
        ;             -  concatenate = [[1,2,3],[4,5,6],[7,8,9],[1,5,9],[2,6],[3],[7],[4,8]] or [[7,4,1],[8,5,2],[9,6,3],[7,5,3],[4,2],[1],[9],[8,6]]
             Ẏ        - tighten = [[1,2,3],[4,5,6],[7,8,9],[1,5,9],[2,6],[3],[7],[4,8],[7,4,1],[8,5,2],[9,6,3],[7,5,3],[4,2],[1],[9],[8,6]]
                      -    i.e.:    row1    row2    row3    diag\   x     x   x   x     col1    col2    col3    diag/   x     x   x   x
                      -    where x's are not long enough to matter for the rest...
                ⁸     - chain's left argument, list of player's moves
              f€      - filter to keep those moves for €ach of those lists to the left
                 L€   - length of €ach result
                   3e - 3 exists in that? (i.e. were any length 3 when filtered down to only moves made?)

s2ZÇƤ€ZFTḢ;Ḃ$ - Main link: list of the moves  e.g. [2,3,4,5,6,7,1,8,9]
s2            - split into twos                    [[2,3],[4,5],[6,7],[1,8],[9]]
  Z           - transpose                          [[2,4,6,1,9],[3,5,7,8]]
    Ƥ€        - for Ƥrefixes of €ach:
   Ç          -   call last link (1) as a monad     [0,0,0,0,0] [0,0,1,1]
      Z       - transpose                          [[0,0],[0,0],[0,1],[0,1],[0]]
       F      - flatten                            [0,0,0,0,0,1,0,1,0]
        T     - truthy indices                     [          6   8  ]
         Ḣ    - head (if empty yields 0)           6
            $ - last two links as a monad:
           Ḃ  -   modulo by 2 (evens are player 2) 0
          ;   -   concatenate                      [6,0]

0

Python 2, 168 byte

import itertools as z
f=lambda g:next(([i%2+1,i+1]for i in range(9) if any(c for c in z.combinations([[0,6,1,8,7,5,3,2,9,4][j]for j in g[i%2:i+1:2]],3)if sum(c)==15)),0)

Uscite (giocatore, round) o 0 per un pareggio.

Mappa il gioco su un quadrato magico 3 per 3 e cerca set di 3 O o X che si sommano a 15.


0

Pulito , 244 ... 220 byte

import StdEnv
f[a,b]i#k= \l=or[and[isMember(c+n)(take i l)\\c<-:"123147159357"%(j,j+2)]\\j<-[0,3..9]&h<-:"\0\0",n<-[h-h,h,h+h]]
|k a=(1,i*2-1)|i>4=(0,0)|k b=(2,i*2)=f[a,b](i+1)
@l=f(map(map((!!)l))[[0,2..8],[1,3..7]])1

Provalo online!

La stringa ripetuta in hcontiene non stampabili ed è equivalente a "\003\001\000\000".


0

Python 2 , 140 136 134 byte

lambda a,i=0:i<9and(any(set(a[i%2:i+1:2])>=set(map(int,t))for t in'123 456 789 147 258 369 159 357'.split())and(i%2+1,i+1)or f(a,i+1))

Provalo online!

EDIT: 4 byte + 2 byte grazie a Eric the Outgolfer.

Emette una tupla (playerNumber, roundNumber) o False se non c'è vincitore.



@Erik - Sì, avrei già dovuto farlo; ma sto combattendo l'influenza e mi fanno male gli occhi :). Grazie!
Chas Brown,

Bene, guarisci presto. :)
Erik the Outgolfer,
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.