Determinar la victoria en Tictactoe

19

¡Juguemos un código de golf!

Dado un estado de tablero de tres en raya (Ejemplo :)

|x|x|o|
|x|o|x|
|o|o|x|

Determina si un juego es un wina loseo cat. Su código debe mostrar cualquiera de estas opciones dado un estado. El juego anterior debería salirlose

Para ser claros: una ganancia se define como 3 xs seguidos (diagonal, horizontal, vertical). una pérdida es de 3 os seguidos, mientras que un catjuego en ninguno en una fila.

Para hacer las cosas interesantes, puede determinar su estructura de entrada para el estado, que luego debe explicar. Por ejemplo, xxoxoxooxes un estado válido como se ve arriba, donde cada uno de los caracteres se lee de izquierda a derecha, de arriba a abajo. [['x','x','o'],['x','o','x'],['o','o','x']]es el juego en matriz multidimensional leído de manera similar. Mientras 0x1a9que hexadecimal 110101001podría funcionar como una compresión adecuada donde 1se puede manipular para xsy 0se puede manipular para o.

Pero esas son solo algunas ideas, estoy seguro de que podría tener muchas propias.

Reglas de juego:

  1. Su programa debe poder aceptar cualquier estado viable.
  2. La forma de entrada debe poder representar cualquier estado.
  3. "El estado ganador debe determinarse desde el tablero"
  4. Asumir una tabla completa
  5. Winantes, losepor ejemplo, en el caso 'xxxoooxxx'

El conteo de personajes más bajo gana

Dylan Madisetti
fuente
1
Me gusta esta estructura de entrada: (win|lose|cat) [xo]{9}donde la primera palabra denota si el juego es ganar, perder o gato (?) Para el jugador x. Capaz de representar cualquier estado.
Runer112
2
¿Puedo sugerir una regla como "El estado ganador debe determinarse a partir del tablero" o "La entrada no debe contener información excepto el estado del tablero"?
undergroundmonorail
3
¿Estamos suponiendo que solo se juegan juegos legales? Si es así, ciertos estados serían imposibles, es decir, XXX OOO XXX, pero de lo contrario, algunos estados de pensión completa incluyen esto como un cuarto resultado imposible, donde X gana pero O también gana.
Riot
10
¿Por qué "gato" fuera de interés?
Chris
77
@DylanMadisetti: nunca lo escuché antes y no se encontró nada en Google para "ganar perder gato". Me hubiera ido con corbata o sorteo personalmente. O en el caso de este juego tal vez "inevitabilidad". ;-) Sin embargo, no me importa mucho en lo que respecta a la competencia. Una cadena es una cadena. ;-)
Chris

Respuestas:

11

Ruby 2.0, 85 caracteres

Aquí hay una solución simple basada en máscara de bits en Ruby:

d=gets.hex
$><<[292,146,73,448,56,7,273,84].map{|m|d&m<1?:lose:d&m<m ?:cat: :win}.max

El tablero se representa como un número hexadecimal, compuesto por nueve bits correspondientes a los nueve cuadrados. 1 es un X, 0 es un O. Esto es como el 0x1a9ejemplo en la pregunta, ¡aunque 0xes opcional!

Probablemente haya una mejor manera de hacer las máscaras de bits que simplemente codificar una gran lista. Felizmente tomaré sugerencias.

Véalo corriendo en Ideone aquí .

Paul Prestidge
fuente
1
Tu lista contiene 273dos veces. ¡Y realmente me gusta la maxidea!
Ventero
1
Oh @Ventero, siempre con las oscuras optimizaciones (gracias)
Paul Prestidge
Puede haber espacios vacíos en un tablero. Su formato de entrada no tiene en cuenta esto y, por lo tanto, no puede representar ningún estado de juego viable.
Stephen Ostermiller
2
@StephenOstermiller regla 4: asume un tablero completo. Tiene razón en que esta regla tal vez se contradiga con las reglas 1 y 2, sin embargo, si lee todos los comentarios sobre la pregunta, creo que esto está dentro del espíritu de la pregunta (los tableros incompletos no están cubiertos, mientras que los tableros completos son ilegales). Sin embargo, creo que octal sería un formato de entrada más fácil de usar que hexadecimal.
Level River St
1
Entendido, pensé que completo significaba algo diferente.
Stephen Ostermiller
10

Mathematica, 84 caracteres

a=Input[];Which[Max@#>2,win,Min@#<1,lose,1>0,cat]&@{Tr@a,Tr@Reverse@a,Tr/@a,Total@a}

Formato de entrada: {{1, 1, 0}, {1, 0, 1}, {0, 0, 1}}

alephalpha
fuente
¿Que esta pasando aqui?
seequ
3
@TheRare Comience desde la derecha. Tr@aes la traza del campo (suma sobre diagonal), Tr@Reverse@aes la traza del campo invertido (algo sobre antia diagonal), Tr/@ase Traplica a cada fila, lo que le da la suma sobre cada fila, Total@ale da la suma sobre cada columna. Básicamente, tienes las 8 líneas que debes verificar. Luego, la Whichcosa se aplica a eso (básicamente una if/elseif/elsedeclaración), donde #representa esa lista de 8 valores. ifhay un 3que ganas, else ifhay un 0que pierdes, else if 1>0(cierto) cat.
Martin Ender
6

Golpe: 283 262 258

Con una interfaz relativamente amigable.

t(){ sed 's/X/true/g;s/O/false/g'<<<$@;}
y(){ t $(sed 's/X/Q/g;s/O/X/g;s/Q/O/g'<<<$@);}
f(){($1&&$2&&$3)||($1&&$5&&$9)||($1&&$4&&$7)||($2&&$5&&$8)||($3&&$5&&$7)||($3&&$6&&$9)||($4&&$5&&$6)||($7&&$8&&$9)}
f $(t $@)&&echo win||(f $(y $@)&&echo lose)||echo cat

Ejecutar bash tictactoe.sh O X O X O X X O X

Nota: la lista de 9 posiciones es una representación matricial estándar. No importa si el tablero está representado como columna mayor o fila mayor, lea de izquierda a derecha o de arriba a abajo; los juegos de ceros y cruces (o tic tac toe si insiste) son simétricos, por lo que el orden de entrada debe ser irrelevante al resultado en cada implementación correcta, siempre que la entrada sea lineal.

Editar: Gracias a hjk por sugerencias de sintaxis de funciones más cortas.

Alboroto
fuente
Considerar en t() { ... }lugar de function t? Puede guardar algunos personajes allí. :)
hjk
Me había olvidado por completo de la sintaxis de la función alternativa, ¡gracias!
Disturbios
No se requieren espacios <<<para guardar otros cuatro caracteres.
Michael Mior
4

Befunge 93-375

Toma una cadena binaria como entrada.

99>~\1-:!!|>v  
>0v>v>v   >^$>v
^+ + +    0<:p:
>#+#+#+    ^246
^+ + +    0<265
>#+#+#+    ^pp6
^+ + +    0<2++
 #+#+#+     55p
   0 0      552
  >^>^>0v   +46
v+ + +  <   ppp
>0 + + + v  444
   v!!-3:<< 246
  v_"ni"v   ppp
  0v" w"<   :+:
  \>,,,,@   266
  ->,,,@    555
  !^"cat"_^ 645
  !>:9-! ^  +:+
  >|        p:p
   >"eso"v  6p6
 @,,,,"l"<  246
            p2p
            >^ 
  v       <^  <

Lee la cadena. Bruteforce lo escribe (la tira más vertical derecha) como una matriz entre

^+ + + 
>#+#+#+
^+ + + 
>#+#+#+
^+ + + 
 #+#+#+

agregando celosía (idk). Determina la suma de las columnas, filas y dos diagnósticos. Compara esos valores con 3 ("ganar") o 0 ("perder"), de lo contrario, si todos los valores son iguales a 1 o 2, entonces empate ("gato").

AndoDaan
fuente
4

GolfScript, 27 caracteres

70&.{~"win""lose"if}"cat"if

El formato de entrada es una cadena que consta de ocho dígitos octales, cada uno de los cuales (de forma redundante) codifica tres cuadrados de placa consecutivos:

  • Los primeros tres dígitos codifican cada uno una sola fila del tablero, de arriba abajo y de izquierda a derecha.
  • Los siguientes tres dígitos codifican cada uno una sola columna del tablero, de izquierda a derecha y de arriba hacia abajo.
  • Cada uno de los dos dígitos finales codifica una de las diagonales (primero desde la parte superior izquierda a la parte inferior derecha, luego desde la parte inferior izquierda a la parte superior derecha).

Para codificar una secuencia (fila / columna / diagonal) de tres cuadrados como un dígito octal, reemplace cada xen la secuencia con un 1 y cadao con un 0, e interprete la secuencia resultante de unos y ceros como un número binario entre 0 y 7 inclusivo.

Este formato de entrada es bastante redundante (todas las posiciones de la junta se codifican al menos dos veces, con la posición central codificado cuatro veces), pero no de forma inequívoca representa ningún posible estado de una tabla de tic-tac-dedo del pie está completamente lleno, y no directamente codificar el ganador en la entrada.

La entrada puede, opcionalmente, contener espacios u otros delimitadores entre dígitos. De hecho, todo lo que realmente le importa al programa es si la cadena de entrada contiene o no los dígitos 7o 0.

Por ejemplo, el tablero de ejemplo:

|x|x|o|
|x|o|x|
|o|o|x|

puede estar representado por la entrada:

651 643 50

Para mayor comodidad, aquí hay un programa GolfScript para convertir un diseño de tablero de arte ASCII, como se muestra en el desafío anterior, en una cadena de entrada adecuada para este programa:

."XOxo"--[{1&!}/]:a[3/.zip"048642"{15&a=}%3/]{{2base""+}%}%" "*

Este convertidor ignora cualquier carácter que no sea xy o, en cualquier caso, en su entrada. Produce una cadena de un solo dígito (completa con delimitadores de espacio como se muestra arriba) adecuada para alimentar el programa de determinación de victorias anterior, por lo que la concatenación de estos dos programas se puede utilizar para determinar el ganador directamente del tablero de arte ASCII.

Además, aquí hay un convertidor inverso, solo para demostrar que la entrada de hecho representa inequívocamente la placa:

.56,48>-- 3<{2base-3>{"ox"=}%n}%"|".@@*+);

PD. Aquí hay una demostración en línea de esta solución.

Ilmari Karonen
fuente
2
El formato de entrada parece un poco engañoso, ya que gran parte del trabajo ocurre en la producción de la entrada.
Arkku
@Arkku: Bueno, sí, pero la pregunta dice explícitamente que "debes determinar tu estructura de entrada para el estado, que luego debes explicar". Incluso muestra una cadena hexadecimal llena de bits como ejemplo de un formato de entrada válido; La única diferencia entre eso y mi formato de entrada es que vuelvo a ordenar y duplicar algunos bits.
Ilmari Karonen
66
Es exactamente la duplicación lo que parece una trampa. (por ejemplo, que no codifican directamente el ganador como la presencia de 7 o 0 en la entrada)
Arkku
Aún así, es una codificación inteligente, es redundante, ¡pero hace que encontrar la solución sea mucho más eficiente que cualquier codificación no redundante!
ARRG
3

Python 2 - 214 bytes

b=eval(raw_input())
s=map(sum,b)
w,l='win','lose'
e="if min(s)<1:print l;a\nif max(s)>2:print w;a"
exec e+'\ns=map(sum,zip(*b))\n'+e
m=b[1][1]
for i in 0,2:
 if m==b[0][i]==b[2][abs(i-2)]:print[l,w][m];a
print'cat'

Estoy seguro de que hay mejoras por hacer.

Correr:

python2 tictactoe.py <<< '[[1,1,1],[1,0,1],[0,1,0]]'

que representa este tablero:

X|X|X
-----
X|O|X
-----
0|X|0

Salidas con una NameErrorexcepción en todos los casos excepto cat.

monorraíl subterráneo
fuente
Whoa, nunca supe <<<! +1 solo por eso.
Greg Hewgill
@GregHewgill Es bastante conveniente. ./whatever <<< 'blah blah blah'es lo mismo echo -n 'blah blah blah' | ./whateverpero sin tener un proceso completamente separado para echo.
undergroundmonorail
@undergroundmonorail echoen bashrealidad es un proceso integrado, por lo que no bifurca un nuevo proceso
Bob
@GregHewgill se llama herejía
3

Haskell, 146 caracteres

Para hacer las cosas interesantes, puede determinar su estructura de entrada para el estado, que luego debe explicar.

OKAY :). Mi representación de un tablero es uno de esos 126 caracteres.

ĻŃŇʼnŊœŗřŚşšŢťŦŨųŷŹźſƁƂƅƆƈƏƑƒƕƖƘƝƞƠƤƳƷƹƺƿǁǂDždžLjǏǑǒǕǖǘǝǞǠǤǯDZDzǵǶǸǽǾȀȄȍȎȐȔȜȳȷȹȺȿɁɂɅɆɈɏɑɒɕɖɘɝɞɠɤɯɱɲɵɶɸɽɾʀʄʍʎʐʔʜʯʱʲʵʶʸʽʾˀ˄ˍˎː˔˜˭ˮ˰˴˼̌

Aquí está la solución en 146 caracteres:

main=interact$(\x->case(head x)of h|elem h "ĻŃœťŦŨųŷŹƁƂƅƈƕƠƤƳƿǂdžǞǤǵǾȀȳȿɁɅɑɒɘɝɠɤɵɽʀʐʽʾː˭ˮ˰˴˼̌"->"lose";h|elem h "ƏƝƞƹǁLjǑǝȍȺɆɈɶɾʎʸ"->"cat";h->"win")

Y así es como funciona, como un script haskell:

import Data.List (subsequences, (\\))
import Data.Char (chr)

-- A set of indexes [0-8] describing where on the board pieces of a single color have been played
-- For example the board "OxO;Oxx;xxO" is indexes [0,2,3,8]
type Play = [Int]

-- There are 126 filled tic tac toe boards when X plays first.
--      (This is a combination of 4 OHs among 9 places : binomial(9 4) = 126)
-- perms returns a list of all such possible boards (represented by the index of their OHs).
perms = filter (\x -> 4 == length x) $ subsequences [0..8]

-- We now create an encoding for plays that brings them down to a single char.
-- The index list can be seen as an 9 bit binary word [0,2,3,8] -> '100001101'
-- This, in turn is the integer 269. The possible boards give integers between 15 and 480.
-- Let's call those PlayInts
type PlayInt = Int

permToInt [] = 0
permToInt (x:xs) = (2 ^ x) + permToInt xs 

-- Since the characters in the range 15-480 are not all printable. We offset the chars by 300, this gives the range 
-- ĻŃŇʼnŊœŗřŚşšŢťŦŨųŷŹźſƁƂƅƆƈƏƑƒƕƖƘƝƞƠƤƳƷƹƺƿǁǂDždžLjǏǑǒǕǖǘǝǞǠǤǯDZDzǵǶǸǽǾȀȄȍȎȐȔȜȳȷȹȺȿɁɂɅɆɈɏɑɒɕɖɘɝɞɠɤɯɱɲɵɶɸɽɾʀʄʍʎʐʔʜʯʱʲʵʶʸʽʾˀ˄ˍˎː˔˜˭ˮ˰˴˼̌
-- Of all distinct, printable characters
uOffset = 300

-- Transform a PlayInt to its Char representation
pIntToUnicode i = chr $ i + uOffset

-- Helper function to convert a board in a more user friendly representation to its Char
-- This accepts a representation in the form "xooxxxoxo"
convertBoard s = let play = map snd $ filter (\(c, i) -> c == 'o') $ (zip s [0..]) :: Play 
    in pIntToUnicode $ permToInt play

--
-- Now let's cook some data for our final result
--  

-- All boards as chars
allUnicode = let allInts = map permToInt perms 
    in map pIntToUnicode allInts

-- Now let's determine which boards give which outcome.

-- These are all lines, columns, and diags that give a win when filled
wins = [
        [0,1,2],[3,4,5],[6,7,8], -- lines
        [0,3,6],[1,4,7],[2,5,8], -- columns
        [0,4,8],[2,4,6] -- diagonals
    ]

isWin :: Play -> Bool   
isWin ps = let triplets = filter (\x -> 3 == length x) $ subsequences ps -- extract all triplets in the 4 or 5 moves played
    in any (\t -> t `elem` wins) triplets -- And check if any is a win line

-- These are OH wins
oWins = filter isWin perms
-- EX wins when the complement board wins
xWins = filter (isWin . complement) perms
    where complement ps = [0..9] \\ ps
-- And it's stalemate otherwise
cWins = (perms \\ oWins) \\ xWins

-- Write the cooked data to files
cookData = let toString = map (pIntToUnicode . permToInt) in do
  writeFile "all.txt" allUnicode
  writeFile "cWins.txt" $ toString cWins
  writeFile "oWins.txt" $ toString oWins
  writeFile "xWins.txt" $ toString xWins

-- Now we know that there are 48 OH-wins, 16 stalemates, and 62 EX wins (they have more because they play 5 times instead of 4).
-- Finding the solution is just checking to which set an input board belongs to (ungolfed :)
main = interact $ \x -> case (head x) of -- Only consider the first input char
    h | elem h "ĻŃœťŦŨųŷŹƁƂƅƈƕƠƤƳƿǂdžǞǤǵǾȀȳȿɁɅɑɒɘɝɠɤɵɽʀʐʽʾː˭ˮ˰˴˼̌" -> "lose" -- This string is == oWins
    h | elem h "ƏƝƞƹǁLjǑǝȍȺɆɈɶɾʎʸ" -> "cat" -- And this one == cWins
    h -> "win"
ARRG
fuente
3

JavaScript, 420 caracteres

if((s&0x3F000)==0x3F000||(s&0x00FC0)==0x00FC0||(s&0x0003F)==0x0003F||(s&0x030C3)==0x030C3||(s&0x0C30C)==0x0C30C||(s&0x30C30)==0x30C30||(s&0x03330)==0x03330||(s&0x30303)==0x30303)return 'win'
if((s&0x3F000)==0x2A000||(s&0x00FC0)==0x00A80||(s&0x0003F)==0x0002A||(s&0x030C3)==0x02082||(s&0x0C30C)==0x08208||(s&0x30C30)==0x20820||(s&0x03330)==0x02220||(s&0x30303)==0x20202)return 'lose'
if((s&0x2AAAA)==0x2AAAA)return 'cat'

En esta versión, scontiene un número entero que representa el estado del tablero de juego. Es una matriz de valores de bits donde dos bits representan cada cuadrado en el tablero:

  • 10 - X
  • 11 - O
  • 00 - Plaza vacía

Esta solución utiliza la manipulación de bits para probar cada una de las ocho configuraciones posibles de "tres en una fila" (las prueba cada una dos veces, una para X y otra para O).

Presento esto con una minificación menor de mi sitio web Tic-Tac-Toe donde esta detectWinfunción está en uso como parte de un juego real de Tic-Tac-Toe.

Stephen Ostermiller
fuente
66
Bueno, esto podría llamarse bruto forzándolo.
seequ
2

Ruby, 84 caracteres

$><<(gets.tr("01","10")[r=/0..(0|.0.)..0|000(...)*$|^..0.0.0/]?:win:~r ?:lose: :cat)

Solución simple basada en RegExp. El formato de entrada es una cadena binaria de 9 dígitos, p. Ej.110101001 para el tablero de ejemplo dado en la pregunta.

Ruby, 78 caracteres

$><<(gets.tr("ox","xo")[r=/o...(o|.o.)...o|ooo|o_.o._o/]?:win:~r ?:lose: :cat)

Formato de entrada: xxo_xox_oox

Ventero
fuente
1

Haskell, 169

main=interact$(\x->last$"cat":[b|(a,b)<-[("ooo","lose"),("xxx","win")],any(==a)x]).(\x->x++(foldr(zipWith(:))(repeat[])x)++map(zipWith(!!)x)[[0..],[2,1,0]]).take 3.lines

Formato de entrada: "X" solo está representado por x"O" solo por o. Dentro de cada fila, los caracteres son simultáneos sin espacios, etc. Las filas están separadas por nuevas líneas.

Genera todas las filas / columnas / diagonales posibles, luego filtra [("ooo","lose"),("xxx","win")]por su existencia en el tablero, luego selecciona la segunda palabra en la tupla, para que sepamos qué jugadores ganaron. Anteponemos "cat"para que podamos tomar el último elemento de la lista como nuestro ganador. Si ambos jugadores ganaron, "win"será el último (las comprensiones de la lista mantienen el orden). Como "cat"siempre es el primero, si existe un ganador, se elegirá, pero de lo contrario todavía existe un último elemento como antecedente"cat" garantía no garantiza la nada.

EDITAR: Afeitó 3 caracteres cambiando la última comprensión de la lista a map.

YawarRaza7349
fuente
1

C, 150 aprox.

Aquí es medianoche y no he hecho ninguna prueba. , pero de todos modos publicaré el concepto. Volveré a eso mañana.

El usuario ingresa dos números octales (quería usar binarios, pero que yo sepa, C solo admite octal):

a representa el cuadrado central, 1 para una X, 0 para una O

b es un número de nueve dígitos que representa los cuadrados del perímetro, dando vueltas alrededor del tablero comenzando en una esquina y terminando en la misma esquina (solo con la repetición de esa esquina), 1 para una X, 0 para una O.

Hay dos formas posibles de ganar:

  1. el cuadrado central es X ( a= 1) y dos cuadrados opuestos también son X ( b&b*4096es distinto de cero)

  2. tres cuadrados perimetrales adyacentes son X ( b/8 & b & b*8no es cero). Esto es solo una victoria válida si el cuadrado del medio es un cuadrado de borde, no un cuadrado de esquina, por lo tanto, es necesario aplicar la máscara mtambién, para evitar los casos de cuadrado de esquina.

La pérdida se detecta utilizando la variable c, que es la inversa de b.

int a,b,c,m=010101010;
main(){
    scanf("%o%o",a,b);c=b^0111111111;
    printf("%s",(a&&b&b*4096)|(b/8&b&b*8&m)?"win":((!a&&c&c*4096)|(c/8&c&c*8)?"lose":"cat"));
}
Level River St
fuente
Olvidó aplicar la máscara men la detección de "pérdida" c/8&c&c*8. He rediseñado su código (sin probar su funcionamiento) de la siguiente manera: int a,b;t(v){return a&&v&v<<12||v/8&v&v*8&0x208208;}main(){scanf("%o%o",a,b);printf("%s",t(b)?"win":t(b^0x1249249)?"lose":"cat");}(130 caracteres). La prueba repetida fue lo suficientemente larga como para extraerla en una función de prueba t(); esto elimina la necesidad de cy m; Las constantes se convierten en hexadecimal para guardar un personaje cada una.
Toby Speight
¡Acabo de ver que printfno necesita una cadena de formato, solo proporcione la cadena de resultado como formato, o putsbien, ya que la pregunta no solicita una nueva línea después de la salida! (ahorra otros 7 caracteres).
Toby Speight
1

Golpetazo, 107 103

Genera y ejecuta un script sed.

Formato de E / S: oxo-oox-xoosalidas lose(use a -para separar las filas). Entrada en stdin. Requiere GNU sed para el ccomando.

He interpretado la regla 5 como "si tanto ganar como perder son posibles, elija ganar".

Código principal

Esta es la respuesta real.

Nada interesante realmente. En él se definen $bcomo /cwinpara salvar a los personajes, a continuación, define la parte condición de victoria de la secuencia de comandos, a continuación, utiliza sed y/x/o/\;s$b/close/para convertir xa oy cwina close(generando así las condiciones de perder). Luego envía las dos cosas y ccat(que se generará catsi no se cumple ninguna condición de ganar / perder) para sed.

b=/cwin
v="/xxx$b
/x...x...x$b
/x..-.x.-..x$b
/x-.x.-x$b"
sed "$v
`sed y/x/o/\;s$b/close/<<<"$v"`
ccat"

Código generado

Este es el script sed generado y ejecutado por el script Bash.

En las expresiones regulares, .coincide con cualquier carácter y luego cTEXTimprime TEXTO y sale si la expresión regular coincide.

Esto puede ejecutarse como un script sed independiente. Tiene 125 caracteres, puede contarlo como otra solución.

/xxx/cwin
/x...x...x/cwin
/x..-.x.-..x/cwin
/x-.x.-x/cwin
/ooo/close
/o...o...o/close
/o..-.o.-..o/close
/o-.o.-o/close
ccat

fuente
1

Pitón 3, 45

La entrada está en i, que es una lista de números que representan cada fila, columna y diagonal del tablero de juego, por ejemplo:

X X O
O X O
O O X

está representado por [6, 2, 1, 4, 6, 1, 7, 4].

Código :('cat','lose','win')[2 if 7 in i else 0 in i]

seudónimo117
fuente
1

Dart - 119

(Ver dartlang.org ).

Versión original con RegExp: 151 caracteres.

main(b,{w:"cat",i,p,z}){
 for(p in["olose","xwin"])
   for(i in[0,2,3,4])
     if(b[0].contains(new RegExp('${z=p[0]}(${'.'*i}$z){2}')))
       w=p.substring(1);
  print(w);
}

La entrada en la línea de comando tiene 11 caracteres, por ejemplo, "xxx | ooo | xxx". Cualquier carácter que no sea xo puede usarse como delimitador.

Deben omitirse los espacios en blanco y las nuevas líneas antes de contar los caracteres, pero elimino el espacio en blanco interno cuando sea posible. Desearía que hubiera una forma más pequeña de hacer la subcadena.

Versión de base de bits recusiva: 119 caracteres. La entrada debe ser un número de 9 bits con 1 que represente 'x' y 0 que represente 'o'.

main(n){
  n=int.parse(n[0]);
  z(b,r)=>b>0?b&n==b&511?"win":z(b>>9,n&b==0?"lose":r):r;
  print(z(0x9224893c01c01e2254,"cat"));
}
lrn
fuente
1

CJam, 39 38 36 caracteres

"ᔔꉚ굌궽渒䗠脯뗠㰍㔚귇籾〳㎪䬔⹴쪳儏⃒ꈯ琉"2G#b129b:c~

Este es un código convertido base para

q3/_z__Wf%s4%\s4%]`:Q3'o*#"win"{Q'x3*#"lose""cat"?}?

que tiene 52 caracteres de largo.

La entrada es simplemente la representación de cadena del tablero que comienza desde la parte superior izquierda, yendo fila por fila. Por ejemplo:

oxooxooox

que da como resultado una winsalida. O

oxooxoxox

que da como resultado una catsalida, etc.

El código simplemente hace las siguientes tres cosas:

  • q3/_ - Divida la cadena en partes de 3, es decir, por fila
  • _z - Copie la matriz por fila y transponga en matriz por columna.
  • __Wf%s4%- Invierta cada fila y obtenga la diagonal de izquierda a derecha. Esta es la diagonal secundaria del tablero.
  • \s4% - Obtener la diagonal principal del tablero
  • ]` - Envuelva todo en la matriz y stringifique la matriz.

Ahora tenemos todos los grupos posibles de 3 del tablero. Simplemente verificamos la existencia de "ooo" y "xxx" para determinar el resultado.

Pruébalo en línea aquí

Optimizador
fuente
1

GNU sed, 25 bytes

Si la entrada es una representación redundante del tablero con vistas separadas para columnas, filas y diagonales, como también se usa en otras respuestas, entonces sed es muy adecuado para verificar el estado final del juego con la menor cantidad de bytes.

Formato de entrada: xxx ooo xxx xox xox xox xox xox (estado del tablero tomado de la pregunta del OP)

/xxx/cwin
/ooo/close
ccat

Si el formato de entrada no es redundante ( xxx ooo xxx), el código sed anterior solo funciona si está precedido por la línea de abajo, lo que hace que el programa tenga 96 bytes de longitud (con el marcador necesario rcontado).

s/(.)(.)(.) (.)(.)(.) (.)(.)(.)/& \1\4\7 \2\5\8 \3\6\9 \1\5\9 \3\5\7/
seshoumara
fuente
1

Golpe: 208 caracteres

y(){ tr '01' '10'<<<$@;}
f(){ x=$[($1&$2&$3)|($1&$5&$9)|($1&$4&$7)|($2&$5&$8)|($3&$5&$7)|($3&$6&$9)|($4&$5&$6)|($7&$8&$9)]; }
f $@;w=$x
f $(y $@)
([ $x -eq 1 ]&&echo lose)||([ $w -eq 1 ]&&echo win)||echo cat

Ejecutar bash tictactoe.sh 0 1 0 1 0 1 1 0 1

Inspirado por esta respuesta .

Michael Mior
fuente
0

VB.net

Con el ejemplo, provide se codifica como el siguiente patrón de bits

q  = &B_100101_100110_011010 ' 00 Empty, 01 = O, 10 = X

Ahora podemos determinar el resultado (o ganador) haciendo lo siguiente.

Dim g = {21, 1344, 86016, 66576, 16644, 4161, 65379, 4368}
Dim w = If(g.Any(Function(p)(q And p)=p),"Lose",If(g.Any(Function(p)(q And p*2)=p*2),"Win","Cat"))
Adam Speight
fuente
0

J - 97 bytes

Bueno, el enfoque más simple disponible. La entrada se toma como 111222333, donde los números representan filas. Leer de izquierda a derecha. El jugador es xy el enemigo es o. Los cuadrados vacíos pueden ser cualquier cosa excepto xo o.

f=:(cat`lose>@{~'ooo'&c)`('win'"_)@.('xxx'&c=:+./@(r,(r|:),((r=:-:"1)(0 4 8&{,:2 4 6&{)@,))3 3&$)

Ejemplos: (NB. Es un comentario)

   f 'xoxxoxxox' NB. Victory from first and last column.
win
   f 'oxxxooxxx' NB. Victory from last row.
win
   f 'ooxxoxxxo' NB. The example case, lost to a diagonal.
lose
   f 'xxooxxxoo' NB. Nobody won.
cat
   f 'xoo xx ox' NB. Victory from diagonal.
win

Código sin golf una explicación

row   =: -:"1                        Checks if victory can be achieved from any row.
col   =: -:"1 |:                     Checks if victory can be achieved from any column.
diag  =: -:"1 (0 4 8&{ ,: 2 4 6&{)@, Checks if victory can be achieved from diagonals.
check =: +./@(row,col,diag) 3 3&$    Checks all of the above and OR's them.

f     =: (cat`lose >@{~ 'ooo'&check)`('win'"_)@.('xxx'&check)
Check if you have won ........................@.('xxx'&check)
 If yes, return 'win' .............. ('win'"_)
 If not                   (cat`lose >@{~ 'ooo'&check)
  Check if enemy won ................... 'ooo'&check
   If yes, return 'lose'   ---`lose >@{~
   If not, return 'cat'    cat`---- >@{~
seequ
fuente
0

Python 2, 120 bytes

b=0b101001110
l=[448,56,7,292,146,73,273,84]
print(['Win'for w in l if w&b==w]+['Lose'for w in l if w&~b==w]+['Cat'])[0]

O Python, 115 bytes desde el shell de Python (2 o 3):

b=0b101001110;l=[448,56,7,292,146,73,273,84];(['Win'for w in l if w&b==w]+['Lose'for w in l if w&~b==w]+['Cat'])[0]

La variable de placa se establece en el formato binario descrito en la pregunta: 1para X, 0para O, de izquierda a derecha, de arriba a abajo. En este caso, 101001110representa

XOX
OOX
XXO

Lo que lleva a la salida: Cat

Cees Timmerman
fuente
¿Cuál es el formato de entrada?
seequ
0

Python ( 73 62 caracteres)

La entrada es cuatro cadenas en minúsculas que representan cuatro vistas distintas de la misma placa, todas concatenadas en una sola cadena: por fila, por columna, diagonal derecha, diagonal izquierda.

ACTUALIZAR

¡Gracias a theRare por señalar esto con un buen contraejemplo! Cada vista del tablero, junto con cada segmento (fila o columna) dentro de un tablero, debe estar separada por un carácter que no sea ni una "x" ni una "o" para que la estructura del tablero se conserve incluso después de la concatenación. Los bordes alrededor de cada vista del tablero serán corchetes ("[" y "]"), y el separador entre filas / columnas será un carácter de tubería "|".

Esto hace que el algoritmo sea simple: solo busque "xxx" u "ooo" para ver si gana o pierde, respectivamente. De lo contrario, es un empate (gato).

Por ejemplo, el tablero (lectura de izquierda a derecha, de arriba a abajo) ...

X | X | X X | O | X O | X | O

... se representa como "[xxx | xox | oxo]" (por filas) + "[xxo | xox | xxo]" (por columnas) + "[xoo]" (diagonal derecha) + [xoo] "(izquierda diag) = "[xxx | xox | oxo] [xxo | xox | xxo] [xoo] [xoo]".

Esta declaración de Python imprime el resultado del juego dada la variable s como entrada:

print 'win' if 'xxx' in s else 'lose' if 'ooo' in s else 'cat'
Beto
fuente
¿Esto funciona para el tablero OXX XOO XOX(debería ser gato)?
seequ
No ... no, no lo hace. ¡Buena atrapada! Supongo que mi solución fue demasiado simple ... ¡Vaya!
bob
No puedo decir que este tipo de solución no se me haya pasado por la cabeza. :)
seequ
0

Haskell (69 caracteres)

i x=take 4$(x>>=(\y->case y of{'7'->"win";'0'->"lose";_->""}))++"cat"

Esto toma la misma entrada como se describe en esta respuesta . Más específicamente, la entrada es de 8 valores octales, que describen el valor binario de cada fila, columna y diagonal. El código hace que cada instancia de 7 "gane", cada instancia de 0 "pierda" y elimina todo lo demás. Luego agrega "gato" al final y toma los primeros 4 caracteres del resultado.

Habrá 4 respuestas posibles: "perder", "gato", "ganar" seguido de una 'l', y "ganar" seguido de una 'c', que las reglas no prohíben :)

Ejemplo de uso:

i "65153806" --outputs "lose"
TheBrownMotie
fuente
0

J: 83

(;:'lose cat win'){::~>:*(-&(+/@:(*./"1)@;@(;((<0 1)&|:&.>@(;|.)(,<)|:)))-.)3 3$'x'=

Uso: simplemente agregue una cadena de X y O y observe cómo funciona la magia. p.ej. 'xxxoooxxx'.

El verbo interno (+/@:(*./"1)@;@(;((<0 1)&|:&.>@(;|.)(,<)|:))) básicamente encajona la matriz binaria original, con la transposición encuadrada junto con las 2 diagonales. Estos resultados se arrasan juntos; se toman sumas de fila para determinar las ganancias y luego se suman. Además llamaré a este verbo Inner.

Para encontrar el ganador, el gancho toma la diferencia de los puntajes entre las matrices binarias normales e inversas (-&Inner -.).

El resto del código simplemente genera las salidas y selecciona la correcta.

jpjacobs
fuente
0

JavaScript, 133 , 114 caracteres

r = '/(1){3}|(1.{3}){2}1|(1.{4}){2}1|(1\|.1.\|1)/';alert(i.match(r)?'WIN':i.match(r.replace(/1/g,0))?'LOSS':'CAT')

La entrada i es una cadena simple con delimitadores para las filas, es decir100|001|100

Editar: actualicé mi método para reemplazar los 1s en la expresión regular con ceros para verificar el caso de pérdida.

thomaux
fuente
Puede eliminar los espacios alrededor =y las comillas alrededor del literal regex. Además, 1...es un personaje más corto que 1.{3}.
nyuszika7h
1
r.test(i)También es un personaje más corto que i.match(r).
nyuszika7h
0

J - 56 (26?) Char

La entrada recibe una matriz 3x3 de nueve caracteres, porque J puede admitir eso como un tipo de datos, LOL.

(win`lose`cat{::~xxx`ooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.)

Ejemplos:

   NB. 4 equivalent ways to input the example board
   (3 3 $ 'xxoxoxoox') ; (_3 ]\ 'xxoxoxoox') ; ('xxo','xox',:'oox') ; (];._1 '|xxo|xox|oox')
+---+---+---+---+
|xxo|xxo|xxo|xxo|
|xox|xox|xox|xox|
|oox|oox|oox|oox|
+---+---+---+---+
   (win`lose`cat{::~xxx`ooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.) 3 3 $ 'xxoxoxoox'
lose
   wlc =: (win`lose`cat{::~xxx`ooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.)
   wlc (3 3 $ 'xoxoxooxo')
cat
   wlc (3 3 $ 'xxxoooxxx')
win

Si se nos permite la codificación Golfscriptish de dígitos octales que representan de forma redundante el estado de cada fila, columna y diagonal, entonces son solo 26 caracteres:

   win`lose`cat{::~7 0<./@i.] 6 5 1 6 4 3 5 0
lose
   f=:win`lose`cat{::~7 0<./@i.]
   f  7 0 7 5 5 5 5 5
win
Algoritmo de tiburón
fuente
0

T-SQL (2012), 110

select max(iif(@&m=0,'lose',iif(@&m=m,'win','cat')))from(VALUES(292),(146),(73),(448),(56),(7),(273),(84))z(m)

La entrada es un número hexadecimal. Esto es más o menos una traducción de la solución ruby ​​a T-SQL bastante agradable y ordenada.

Michael B
fuente
0

Javascript 1.6, 71 caracteres

Asumo la entrada como una matriz gameque contiene cada fila, cada columna y cada diag como una cadena de 3 caracteres. Similar a la respuesta de bob , pero viene en una matriz, no como una cadena concatenada.

alert(game.indexOf("xxx")>=0?"win":game.indexOf("ooo")>=0?"lose":"cat")

EDITAR @ nyuszika7h 's comentario (67 caracteres)

alert(~game.indexOf("xxx")?"win":~game.indexOf("ooo")?"lose":"cat")
JNF
fuente
Puede usar en ~game.indexOf("xxx")lugar de game.indexOf("xxx")>=0, lo mismo para el otro.
nyuszika7h
0

Java 7, 260 bytes

String c(int[]s){int a[]=new int[8],x=0,y;for(;x<3;x++){for(y=0;y<3;a[x]+=s[x*3+y++]);for(y=0;y<3;a[x+3]+=s[y++%3]);}for(x=0;x<9;y=s[x],a[6]+=x%4<1?y:0;a[7]+=x%2<1&x>0&x++<8?y:0);x=0;for(int i:a)if(i>2)return"win";for(int i:a)if(i<1)return"loose";return"cat";}

Sin golf y casos de prueba:

Pruébalo aquí

class M{
  static String c(int[] s){
    int a[] = new int[8],
        x = 0,
        y;
    for(; x < 3; x++){
      for(y = 0; y < 3; a[x] += s[x * 3 + y++]);
      for (y = 0; y < 3; a[x + 3] += s[y++ % 3]);
    }
    for(x = 0; x < 9; y = s[x],
                      a[6] += x % 4 < 1
                               ? y
                               : 0,
                      a[7] += x % 2 < 1 & x > 0 & x++ < 8
                               ? y
                               : 0);
    x = 0;
    for(int i : a){
      if(i > 2){
        return "win";
      }
    }
    for(int i : a){
      if(i < 1){
        return "loose";
      }
    }
    return "cat";
  }

  public static void main(String[] a){
    /*  xxo
        xox
        oox  */
    System.out.println(c(new int[]{ 1, 1, 0, 1, 0, 1, 0, 0, 1 }));
    /*  xxx
        ooo
        xxx  */
    System.out.println(c(new int[]{ 1, 1, 1, 0, 0, 0, 1, 1, 1 }));
    /*  xxo
        oox
        xox  */
    System.out.println(c(new int[]{ 1, 1, 0, 0, 0, 1, 1, 0, 1 }));
  }
}

Salida:

loose
win
cat
Kevin Cruijssen
fuente
0

APL (NARS), 69 caracteres, 138 bytes

{w←3 3⍴⍵⋄x←(+/1 1⍉⊖w),(+/1 1⍉w),(+⌿w),+/w⋄3∊x:'win'⋄0∊x:'lose'⋄'cat'}

La entrada debe ser una matriz de 3x3 o una matriz lineal de 9 elementos que puede ser solo 1 (para X) y 0 (para O), el resultado será "cat" si nadie gana, "perder" si O gana, "ganar "si X gana. No hay verificación para una placa o entrada inválida si una matriz tiene menos de 9 elementos o más o verifica cada elemento <2.

Como comentario: convertiría la entrada en una matriz de 3x3 y construiría una matriz llamada "x" donde los elementos son la suma de cada columna de fila y diagonal.

Algunos ejemplos de prueba se muestran de otros:

  f←{w←3 3⍴⍵⋄x←(+/1 1⍉⊖w),(+/1 1⍉w),(+⌿w),+/w⋄3∊x:'win'⋄0∊x:'lose'⋄'cat'}
  f 1 2 3
win
  f 0 0 0
lose
  f 1 0 1  1 0 1  1 0 1
win
  f 0 1 1  1 0 0  1 1 1
win
  f 0 0 1  1 0 1  1 1 0
lose
  f 1 1 0  0 1 1  1 0 0
cat
  f 1 1 0  0 1 0  0 0 1
win
  f 1 1 0  1 0 1  0 0 1
lose
RosLuP
fuente