Connect Four Validator

20

Introdução

O Connect Four é um jogo no qual você tenta obter quatro em sequência: horizontal, vertical ou diagonal. Neste código de golfe, tentaremos descobrir quem ganhou, considerando um tabuleiro de jogo. Sempre haverá um vencedor e apenas um vencedor.


Tarefa

Dado um quadro do Connect Four, descubra quem é o vencedor: Xou Y. Sempre haverá um vencedor e apenas um vencedor. O tamanho do tabuleiro sempre será de 6 por 7, como na figura do jogo.

Em um quadro, o quadro a seguir, nesse caso, Xé vermelho e Yazul:

insira a descrição da imagem aqui

Sua entrada seria:

OOOOOOO
OOOOOOO
OOOOOOO
OOOOXOO
OOOXXOO
OOXYYYY

Você pode separar as linhas do jogo por caracteres de nova linha (como acima), sem caracteres de divisão, dividir as linhas em uma matriz ou lista, ou pode inserir uma matriz de caracteres.

Saída correta para este exemplo:

Y

Y tem quatro seguidas; então, Y é o vencedor. Então, produzimos Y.


Casos de teste

Entrada:

OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO
OOYYOOO
OYXXXXO

Saída:

X

Entrada:

OOOOOOO
OOOOOOO
OOOOOOO
XXXXOOO
YXYYOOO
YXYYXYX

Saída:

X

Entrada:

YXYYXOO
XYXXYOO
XXXYYOO
YYYXXOO
XXYYYYO
XXYYXXO

Saída:

Y

Entrada:

OOOOOOO
OOOOOOO
OYOOOOO
OOYOOOO
OOOYOOO
OOOOYOO

Saída:

Y

Entrada:

OOOOOOO
OOOOOOO
OYOOOOX
OOYOOOX
OOOXOOX
OXOXYOX

Saída:

X

Pontuação

Menor número de bytes ganhos!

Neil
fonte
Este é o desafio perfeito para PMA / Caracóis codegolf.stackexchange.com/questions/47311/...
Jerry Jeremias
2
Podemos supor que o vencedor sempre terá mais um token que o perdedor?
matemática viciado em
1
@ mathjunkie Eu estava errado, você não pode assumir isso.
21417 Neil
3
@nfnneil a saída precisa ser X ou Y ou podemos escolher duas outras saídas consistentes para indicar o vencedor?
Martin Ender
1
Podemos escolher usar outros caracteres como entrada? Ou para inserir uma matriz numérica?
Luis Mendo

Respostas:

2

Geléia , 19 bytes

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

Experimente online!

O núcleo desta resposta é copiado da minha resposta para esta pergunta muito semelhante .

Explicação

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 simples: pegamos todas as linhas, colunas, diagonais e antidiagonais (como no validador n-rainhas), pegamos todas as substrings de comprimento 4 delas e as classificamos de maneira que a linha vencedora de 4 classifique o fim. (Precisamos do desempate, caso haja um OOOOadicional ao XXXXor YYYY.) Pegue o último elemento do último elemento e isso será Xou Yconforme necessário.


fonte
6

Retina, 51 48 bytes

Agradecimentos a Martin Ender por salvar 3 bytes

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

Experimente Online!

Recebe entrada como uma lista de linhas separada por vírgula

viciado em matemática
fonte
Você pode economizar alguns bytes usando um estágio jogo e encurtando (.{7}X){3}|XXXa (.{7}X|X)\4\4: tio.run/nexus/retina#fc4xCsMwDAXQPfcI2GC6NDS5QaeipcP/...
Martin Ender
1
@ MartinEnder Não vejo como você pode usar \4- você deseja repetir o efeito da .{7}string, não da correspondência. (E grupos de equilíbrio seria provavelmente muito tempo.)
Neil
1
@ Neil oh sim, deixa pra lá, de alguma forma eu não considerava que existem outras células OXY além da correspondência na grade. usar o estágio de correspondência ainda salva 3 bytes.
Martin Ender
5

Javascript (ES6), 54 55

Editar 1 byte salvo graças @Arnauld

Eu apenas verifico se X é o vencedor, pois sempre haverá um vencedor e apenas um vencedor

Input é uma string com qualquer separador, como na resposta 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
fonte
@Arnauld bem, obrigado
edc65
4

Geléia , 25 22 bytes

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

Leva uma lista de seqüências de caracteres (ou lista de lista de caracteres) formadas por X, Ye O(também funcionaria com substituições, de modo que o espaço tenha um ordinal inferior aos dois contadores).

Experimente online! ou execute uma versão aumentada que use uma cadeia de linhas múltiplas.

Quão?

Œ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
fonte
4

JavaScript (ES6), 77 76 69 bytes

Economizou 7 bytes graças a Neil

Aceita entrada como uma string separada por algo , em que algo é basicamente qualquer caractere.

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

Casos de teste

Arnauld
fonte
Por que não usar b.match()? Deve economizar na RegExpchamada.
21417 Neil
@ Neil eu esqueci totalmente que match()estava fazendo uma conversão implícita para RegExp. Obrigado!
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]))]

Leva uma lista de seqüências de caracteres ou uma lista de lista de caracteres. Codificado para 6 linhas por 7 colunas, conforme a especificação garante.

Experimente online!

Jonathan Allan
fonte
2

PHP, 71 bytes

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

Versão Online

Jörg Hülsermann
fonte
2

Python 2 , 201 143 129 128 128 107 Bytes

Decidi adicionar horizontal, vertical e diagonal em uma lista e, em seguida, adicionar incremento e, em seguida, procurar por X por vezes. E como sempre haverá um vencedor, posso assumir que Y ganhou se X não. Este código leva uma matriz de todas as partes diferentes e lugares vazios.

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

Experimente online!

Créditos

Neil
fonte
É perfeitamente aceitável responder a si mesmo.
Jonathan Allan
Sem olhar muito para ele, parece haver espaços em branco inúteis em: i:] for, i, r, r] fore 1 for.
Yytsi
@TuukkaX Obrigado pela contribuição, atualizada.
21417 Neil
Além disso, *(len(m)-1)poderia ser *~-len(m). Como funciona.
Yytsi
O ] fore 1 forainda estão lá.
Yytsi
1

K (ngn / k) , 58 55 bytes

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

Experimente online!

{ } função com argumento x

+!6 7 todos os pares possíveis de 0..5 e 0..6

{ }' para cada um deles

4#1-+!3 3 são 4 das 8 direções ortogonais: (1 1;1 0;1 -1;0 1)

3+[ ]\&4comece com uma lista de quatro zeros ( &4) e faça 3 etapas em cada uma das direções

x+/:/: comece de cada posição possível e siga as etapas em cada direção possível

,/concatenar. neste ponto, temos uma matriz de 4 listas de pares de coordenadas, algumas delas se estendendo além do quadro

x ./:/: procure as células correspondentes de x

88<quais deles são "Y"-s? (88 é o código ascii de "X")

&/'quais 4 listas consistem apenas de "Y"-s? (e reduza cada)

|/existe pelo menos um desses? (ou reduzir)

"XY"@se falso retorno "X", se verdadeiro retorno"Y"

ngn
fonte
1

Zsh , 207 ... 159 bytes

Histórico de versões: 4 iterações para ~ 25 bytes na primeira semana; mais 3 iterações para ~ 25 bytes 6 meses depois.

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

( primeiro ) ( segundo ) ( terceiro ) ( quarto ) ( quinto ) ( sexto ) Experimente online!

No rodapé, imprimo a placa de entrada e a matriz que construímos a partir dela para stderr. Role para baixo para depurar para vê-los. A matriz que construímos é muito mais longa agora, já tque um produto cartesiano com placa de entrada todas as chamadas. (Ei, encurtou o código em alguns bytes.)

Há muito o que abordar aqui, então mudei os comentários (sexta edição) para uma essência anotada .

(tl; dr: concatena transposições da matriz original, mas mantenha-as separadas)

GammaFunction
fonte