Connect Four Validator

20

Introducción

Connect Four es un juego en el que intentas obtener cuatro en fila: horizontal, vertical o diagonal. En este código de golf, intentaremos encontrar quién ganó, dado un tablero de juego. Siempre habrá un ganador y solo un ganador.


Tarea

Dado un tablero de Connect Four, descubra quién es el ganador: Xo Y. Siempre habrá un ganador y solo un ganador. El tamaño del tablero siempre será de 6 por 7, como se ve en el cuadro de juego.

Dado un tablero, el siguiente tablero, en este caso, Xes rojo y Yazul:

ingrese la descripción de la imagen aquí

Su aporte sería:

OOOOOOO
OOOOOOO
OOOOOOO
OOOOXOO
OOOXXOO
OOXYYYY

Puede separar las filas del juego por carácter de nueva línea (como arriba), sin dividir caracteres, dividir las filas en una matriz o lista, o puede ingresar una matriz de caracteres.

Salida correcta para este ejemplo:

Y

Y tiene cuatro en fila; entonces, Y es el ganador. Entonces, sacamos Y.


Casos de prueba

Entrada:

OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO
OOYYOOO
OYXXXXO

Salida:

X

Entrada:

OOOOOOO
OOOOOOO
OOOOOOO
XXXXOOO
YXYYOOO
YXYYXYX

Salida:

X

Entrada:

YXYYXOO
XYXXYOO
XXXYYOO
YYYXXOO
XXYYYYO
XXYYXXO

Salida:

Y

Entrada:

OOOOOOO
OOOOOOO
OYOOOOO
OOYOOOO
OOOYOOO
OOOOYOO

Salida:

Y

Entrada:

OOOOOOO
OOOOOOO
OYOOOOX
OOYOOOX
OOOXOOX
OXOXYOX

Salida:

X

Puntuación

¡La menor cantidad de bytes gana!

Neil
fuente
Este es el desafío perfecto para PMA / Snails codegolf.stackexchange.com/questions/47311/…
Jerry Jeremiah
2
¿Podemos suponer que el ganador siempre tendrá una ficha más que el perdedor?
adicto a las matemáticas
1
@mathjunkie Me equivoqué, no puedes asumir eso.
Neil
3
@nfnneil ¿la salida tiene que ser X o Y o podemos elegir otras dos salidas consistentes para indicar el ganador?
Martin Ender
1
¿Podemos elegir usar otros caracteres como entrada? ¿O para ingresar una matriz numérica?
Luis Mendo

Respuestas:

2

Jalea , 19 bytes

UŒD;ŒD;Z;ṡ€4;/ṢEÞṪṪ

Pruébalo en línea!

El núcleo de esta respuesta se copia de mi respuesta a esta pregunta muy similar .

Explicación

UŒD;ŒD;Z;ṡ€4;/ṢEÞṪṪ
   ;  ; ;             Append {the input} and the following three values:
UŒD                     the antidiagonals of {the input};
    ŒD                  the diagonals of {the input};
       Z                the transposed {input}.
         ṡ 4          Find all length-4 substrings
          €             of each subarray within that.
            ;/        Flatten one level.
                Þ     Sort, with the following sort order:
               E        If all elements are the same, sort later.
              Ṣ         Tiebreak via lexicographical order.
                 ṪṪ   Take the last element of the last element.

Bastante simple: tomamos todas las filas, columnas, diagonales y antidiagonales (al igual que en el validador n-reinas), luego tomamos todas las subcadenas de longitud 4 de esas, luego las ordenamos de tal manera que la línea ganadora de 4 se clasifique para el fin. (Necesitamos el desempate en caso de que haya un OOOOcomplemento al XXXXo YYYY.) Tome el último elemento del último elemento, y eso será Xo Ysegún sea necesario.


fuente
6

Retina, 51 48 bytes

Gracias a Martin Ender por guardar 3 bytes

M`X((.{6}X){3}|(.{8}X){3}|(.{7}X){3}|XXX)
T`d`YX

Pruébalo en línea!

Toma datos como una lista de filas separadas por comas

adicto a las matemáticas
fuente
Puede guardar algunos bytes utilizando una etapa de coincidencia y acortando (.{7}X){3}|XXXa (.{7}X|X)\4\4: tio.run/nexus/retina#fc4xCsMwDAXQPfcI2GC6NDS5QaeipcP/…
Martin Ender
1
@MartinEnder No veo cómo puede usarlo \4: desea repetir el efecto de la .{7}cadena coincidente, no. (Y los grupos de equilibrio probablemente serían demasiado largos).
Neil
1
@Neil oh sí, no importa, de alguna manera no consideré que hay otras celdas OXY además de la coincidencia en la cuadrícula. el uso de la etapa de coincidencia aún guarda 3 bytes.
Martin Ender
5

Javascript (ES6), 54 55

Editar 1 byte guardado gracias @Arnauld

Solo verifico si X es el ganador, ya que siempre habrá un ganador y solo un ganador

La entrada es una cadena con cualquier separador, como en la respuesta de @ Arnauld

F=    
b=>'YX'[+[0,6,7,8].some(x=>b.match(`X(.{${x}}X){3}`))]

;['OOOOOOO OOOOOOO OOXOOOO OOXOOOO OOXOOOO OOXOYYY'
 ,'OOOOOOO OOOOOOO OOXOOOO OOYXOOO OOYOXOO OOYYOXY'
 ,'OOOOOOO,OOOOOOO,OOOOOOO,OOOOOOO,OOYYOOO,OYXXXXO'
 ,'OOOOOOO,OOOOOOO,OOOOOOO,XXXXOOO,YXYYOOO,YXYYXYX'
 ,'YXYYXOO,XYXXYOO,XXXYYOO,YYYXXOO,XXYYYYO,XXYYXXO']
.forEach(s => console.log(s,F(s)))

edc65
fuente
@Arnauld bien, gracias
edc65
4

Jalea , 25 22 bytes

ŒgL⁼¥Ðf
;UŒD€;Z;$ç€4FṀ

Toma una lista de cadenas (o lista de caracteres) formada por X, Yy O(también funcionaría con reemplazos de manera que el espacio tenga un ordinal más bajo que ambos contadores).

Pruébalo en línea! o ejecute una versión aumentada que tome una cadena multilínea.

¿Cómo?

ŒgL⁼¥Ðf - Link 1, runs of given length: list A, length B  e.g. "XYYYXXO", 4
Œg      - group runs of equal elements of A                     ["X","YYY","XX","O"]
     Ðf - filter keep:
    ¥   -     last two links as a dyad:
  L     -         length                                         1   3     2    1
   ⁼    -         equal to B?         (none kept in this case->) 0   0     0    0

;UŒD€;Z;$ç€4FṀ - Main link: list of list of chars (or list of stings) I
 U             - reverse each row of I
;              - I concatenated with that
  ŒD€          - positive diagonals of €ach (positive and negative diagonals)
        $      - last two links as a monad:
      Z        -     transpose of I (i.e. the columns)
       ;       -     concatenated with I (columns + rows)
     ;         - concatenate (all the required directional slices)
         ç€4   - call the last link (1) as a dyad for €ach with right argument = 4
            F  - flatten the result
             Ṁ - take the maximum ('Y'>'X'>'O') - this has the bonus effect of returning:
                               'Y' or 'X' for a winning board; and
                               'O' or '' for a (valid) game in progress.
Jonathan Allan
fuente
4

JavaScript (ES6), 77 76 69 bytes

Guardado 7 bytes gracias a Neil

Toma la entrada como una cadena separada por algo , donde algo es básicamente cualquier carácter.

b=>[...'XXXXYYYY'].find((c,i)=>b.match(`(${c}.{${(i%4+6)%9}}){3}`+c))

Casos de prueba

Arnauld
fuente
¿Por qué no usar b.match()? Debería ahorrar en la RegExpllamada.
Neil
@Neil Olvidé totalmente que match()estaba haciendo una conversión implícita a RegExp. ¡Gracias!
Arnauld
3

Python 2 , 143 bytes

m=input()
u=[r[::-1]for r in m]
print"YX"[any(any('X'*4in''.join(t[i][j-i]for i in range(j+1))for j in range(6))for t in(m[::-1],m,u,u[::-1]))]

Toma una lista de cadenas o una lista de caracteres. Codificado para 6 filas por 7 columnas, como lo garantiza la especificación.

Pruébalo en línea!

Jonathan Allan
fuente
2

PHP, 71 bytes

echo preg_match('#X(XXX|(.{8}X){3}|(.{7}X){3}|(.{9}X){3})#',$argn)?X:Y;

Versión en línea

Jörg Hülsermann
fuente
2

Python 2 , 201 143 129 128 107 Bytes

Decidí agregar horizontal, vertical y diagonal juntos en una lista y luego agregar un incremento y luego buscar X por veces. Y dado que siempre habrá un ganador, puedo suponer que Y ganó si X no. Este código toma una matriz de todas las diferentes piezas y lugares vacíos.

lambda m:"YX"[any("X"*4in"".join(a)for a in zip(*m)+m+zip(*["0"*(7-i)+m[i]+"00"*i+m[i]for i in range(6)]))]

Pruébalo en línea!

Créditos

  • De 129 a 107 bytes solo por ASCII .
Neil
fuente
Es perfectamente aceptable contestarse a uno mismo.
Jonathan Allan
Sin mirar demasiado a ella, parece que hay espacios en blanco inútiles en: i:] for, i, r, r] fory 1 for.
Yytsi
@TuukkaX Gracias por el aporte, actualizado.
Neil
Además, *(len(m)-1)podría ser *~-len(m). Cómo funciona.
Yytsi
El ] fory 1 fortodavía están allí.
Yytsi
1

K (ngn / k) , 58 55 bytes

{"XY"@|/&/'88<x ./:/:,/{x+/:/:+3+[4#1-+!3 3]\&4}'+!6 7}

Pruébalo en línea!

{ } funcionar con argumento x

+!6 7 todos los pares posibles de 0..5 y 0..6

{ }' para cada uno de ellos

4#1-+!3 3 son 4 de las 8 direcciones orto-diagonales: (1 1;1 0;1 -1;0 1)

3+[ ]\&4comience con una lista de cuatro ceros ( &4) y realice 3 pasos en cada una de las direcciones

x+/:/: comenzar desde cada posición posible y dar los pasos en cada dirección posible

,/concatenar. en este punto tenemos una matriz de 4 listas de pares de coordenadas, algunas de ellas extendidas más allá del tablero

x ./:/: buscar las celdas correspondientes de x

88<¿cuáles de ellos son "Y"-s? (88 es el código ASCII de "X")

&/'"Y"¿Qué 4 listas consisten solo en -s? (y-reduce-cada)

|/¿hay al menos uno de esos? (o-reducir)

"XY"@si es falso "X", si es verdadero"Y"

ngn
fuente
1

Zsh , 207 ... 159 bytes

Historial de versiones: 4 iteraciones para ~ 25 bytes la primera semana; luego 3 iteraciones más por ~ 25 bytes 6 meses después.

t(){a=($^a-$^@_);for s l (${w:^^argv})s+=$l&&for ((i=0;i++<$#s;))a[i]+=$s[i];}
w=(+)
t $@
for s;w[++j]=${(l:j:)}_
t $@
t ${(Oa)@}
[[ $a = *XXXX* ]]&&<<<X||<<<Y

( primero ) ( segundo ) ( tercero ) ( cuarto ) ( quinto ) ( sexto ) ¡ Pruébelo en línea!

En el pie de página, imprimo tanto la placa de entrada como la matriz que construimos a partir de ella en stderr. Desplácese hacia abajo para depurar para verlos. La matriz que construimos es mucho más larga ahora, ya que ttiene un producto cartesiano con placa de entrada en cada llamada. (Oye, acortó el código en unos pocos bytes).

Hay mucho que cubrir aquí, así que moví los comentarios (sexta edición) a una esencia anotada .

(tl; dr: concatenar transposiciones de la matriz original, pero asegúrese de mantenerlas separadas)

Función Gamma
fuente