Déterminer le vainqueur Tic-Tac-Toe (basé sur le tour)


26

Jouons au golf de code!

Le défi est de trouver le vainqueur d'une partie de Tic-Tac-Toe.

Cela a été fait à plusieurs reprises en donnant un tableau qui a un gagnant clair, mais voici la torsion:

Les cellules sont numérotées comme ceci:

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

Vous obtenez un tableau d'exactement 9 coups comme ça:

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

Ceci est analysé comme suit:

  • Le joueur 1 marque la cellule 3
  • Le joueur 2 marque la cellule 5
  • Le joueur 1 marque la cellule 6
  • Le joueur 2 marque la cellule 7
  • Le joueur 1 marque la cellule 9
  • Le joueur 1 a gagné

Remarque: Le jeu ne s'arrête pas après qu'un joueur a gagné, il peut arriver que le joueur perdant réussisse à en obtenir trois d'affilée après le joueur gagnant, mais seule la première victoire compte.

Votre travail consiste maintenant à obtenir 9 numéros en entrée et en sortie du joueur gagnant et du tour au cours duquel la victoire a eu lieu. Si personne ne gagne, sortez quelque chose de constant de votre choix. Vous pouvez recevoir des entrées et fournir des sorties par n'importe quel moyen / format standard.

S'amuser!

Quelques exemples supplémentaires comme demandé:

{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
Bienvenue chez PPCG! C'est un bon premier article, mais généralement nous n'aimons pas les formats d'entrée / sortie très restrictifs . Envisageriez-vous de supprimer le "Joueur X gagne au tour Y" et laissez-nous la sortie dans un format raisonnable, comme une liste [X, Y]? En cas d'égalité, pouvons-nous produire une autre valeur cohérente à la place? Je le recommande, car l'impression de ces cordes exactes ne fait pas vraiment partie du golf. Pour de futures idées de défis, je recommande d'utiliser le bac à sable . :-)
M. Xcoder

Désolé mon mauvais. Je pense que c'est correct maintenant.
Grunzwanzling

Lisez le défi jusqu'à la fin, je dis qu'il peut y avoir un tirage au sort et que vous pouvez produire quelque chose de votre choix quand cela se produit. Je retourne {2,6} lorsque le joueur 2 gagne au tour 6 et {0,0} lorsque personne ne gagne.
Grunzwanzling

Pouvons-nous utiliser tout index 0? (cellules, joueurs, rondes)
Arnauld

1
"Vous obtenez un tableau d'exactement 9 coups comme ça: {3, 5, 6, 7, 9, 8, 1, 2, 3}" - devrait 3vraiment apparaître deux fois?
Jonathan Allan

Réponses:


8

Rétine , 114 octets

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

Essayez-le en ligne! Basé sur ma réponse à Tic-Tac-Toe - X ou O? . Sorties X<N>si le premier joueur gagne après les Ntours, O<N>si le deuxième joueur gagne, Tsi aucun ne gagne. Explication:

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

Crée un plateau interne et marque également chaque coup avec le joueur dont c'est le coup.

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

Applique un coup.

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

Recherche une victoire, et s'il en trouve une, remplacez le plateau par le gagnant et le nombre de coups restants.

.*¶
T

Si les mouvements sont épuisés et que personne n'a gagné, le jeu est à égalité.

T`d`Rd

Calculez le nombre de tours à partir du nombre de coups restants.


4
C'est l'une des réponses les plus voluptueuses que j'ai vues ici.
Lord Farquaad

6

MATL , 39 octets

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

La sortie est

  • 1et R, sur des lignes distinctes, si l'utilisateur 1 gagne au tour R ;
  • 0et R, sur des lignes distinctes, si l'utilisateur 2 gagne au tour R ;
  • vide si personne ne gagne.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

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 octets

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

Explication

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=[])

Pourriez-vous fournir une explication ou une version non golfée, s'il vous plaît? Je suis intéressé à comprendre votre solution.
Jack

4

Java (OpenJDK 8) , 445 octets

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

Essayez-le en ligne!

La valeur de retour {1,8} signifie que le joueur 1 a gagné au tour 8. La valeur de retour {0,0} signifie match nul.


5
Sauf si vous supprimez tous les espacements inutiles, cette réponse est considérée comme invalide en raison du manque d'effort de golf. De plus, il n'est pas vraiment recommandé de répondre à votre propre défi aussi rapidement, et vous voudrez peut-être ajouter un lien TIO afin que nous puissions tester votre code.
M. Xcoder


Je suis désolé, j'ai copié la mauvaise chose. Il est en fait beaucoup plus court
Grunzwanzling

Vous pouvez voir les conseils pour jouer au golf en Java pour supprimer certains octets. Par exemple, falsepeut être remplacé par 1<0et l'espace après le premier ]peut être supprimé.
user202729

442 octets . La raison pour laquelle la section "En-tête" et "Pied de page" existe également sur TIO est que vous n'avez pas besoin de commenter //Code that was submittedet //End of code.
user202729

2

Kotlin , 236 octets

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

Embellie

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

Tester

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 octets

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)

Essayez-le en ligne! ou Essayez tous les cas de 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 octets

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)

Le format de sortie est winner number:roundou -1pour une égalité. Le joueur 2 est le 0joueur 1 1. Entrée sous la forme d'une chaîne non éliminée de nombres carrés indexés à 1.


1

Gelée , 35 octets

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

Un lien monadique prenant une liste des mouvements et renvoyant une liste, [move, player]où les joueurs sont identifiés comme 1(le premier à agir) et 0(le second à agir).

Essayez-le en ligne!

Comment?

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 octets

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)

Sorties (joueur, tour) ou 0 pour une égalité.

Mappe le jeu sur un carré magique 3 par 3 et recherche des ensembles de 3 Os ou X totalisant 15.


0

Nettoyer , 244 ... 220 octets

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

Essayez-le en ligne!

La chaîne itérée en hcontient non imprimable et est équivalente à "\003\001\000\000".


0

Python 2 , 140 136 134 octets

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

Essayez-le en ligne!

EDIT: 4 octets + 2 octets thx à Eric l'Outgolfer.

Génère un tuple (playerNumber, roundNumber) ou False s'il n'y a pas de gagnant.



@Erik - Yah, j'aurais déjà dû le faire; mais je lutte contre la grippe et mes yeux me faisaient mal :). THX!
Chas Brown

Eh bien, va bien bientôt. :)
Erik the Outgolfer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.