O dicionário Tic Tac Toe

17

Um TicTacToejogo pode ser representado por uma sequência que indica a sequência de posições à medida que os jogadores fazem seu movimento.

0 1 2
3 4 5
6 7 8

Suponha que Xsempre toque primeiro.

Portanto, uma sequência de "012345678" indica o jogo

XOX
OXO
XOX

Observe que o jogo já está ganho quando o jogador Xmarca 6, nesse ponto em que o jogo termina, concedendo uma vitória a X. (ou seja, ignore os movimentos restantes quando o jogador vencer)

Seu desafio (código) é imprimir todos os jogos (ordem classificada) e seus resultados.

O formato

<movesequence>:<result>\n

por exemplo:

012345678:X
012345687:X
012345768:X
...

Indique Xpara o 1º jogador vencedor, Opara o segundo jogador e Dpara Empates.

Haverá 9!(362880) jogos.

Aqui estão alguns dados para verificar seus resultados.

'X' Wins: 212256 
'O' Wins: 104544 
Draws : 46080 

Este é um codegolf, e o tempo de execução deve ser dentro de um minuto. Diverta-se!

EDIT: Removido o excesso de detalhes, e apenas imprimi-lo stdout. Não há necessidade de criar um arquivo.

st0le
fonte
2
Estou recebendo números diferentes aqui: 212256 vitórias em X, 104544 vitórias em O e 46080 empates (e a Wikipedia parece concordar comigo ).
Ventero
@ Ventero, vou verificar novamente, mas não vejo nenhuma referência a esses números na página.
st0le
@ Ventero, você está certo, eu vou editar essa parte. publicará o md5sum em breve.
st0le
11
A resposta do Ruby não é a mais curta, portanto não deve ser a resposta aceita de acordo com seus critérios de pontuação (código-golfe).
mbomb007

Respostas:

3

Ruby 1.9, 201 caracteres

r=*[*l=0..8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6].each_slice(3)
w=->a{r.any?{|b|b&a==b}}
[*l].permutation(9){|a|u=[[],[]];i=-1
u[i%2]<<a[i+=1]while !((x=w[u[1]])||o=w[u[0]])&&i<8
puts a*""+":#{x ??X:o ??O:?D}"}

Ligeiramente golfe até agora. Demora cerca de 45 segundos para concluir aqui.

  • Edit: (268 -> 249) Grava no stdout em vez de em um arquivo
  • Edit: (249 -> 222) Não preencha previamente o array com os movimentos de cada jogador.
  • Edit: (222 -> 208) Maneira mais curta de descobrir se um jogador venceu
  • Edit: (208 -> 213) Voltar para 213, a solução anterior era muito lenta.
  • Edit: (213 -> 201) Alguns rearranjos, espaços em branco removidos
Ventero
fonte
Editei a pergunta um pouco, você não precisa criar um arquivo agora, basta imprimi-lo.
st0le 19/02/11
4

J, 124 caracteres

((],~':',~1":[){&'DOX'@(</+2*>/)@:(<./"1)@:(((2{m/.@|.),(2{m/.),m"1,>./)"2)@(<:@(>:%2|]),:(%(2|>:)))@(3 3$]))"1((i.!9)A.i.9)

X vence, O vence e empate conta.

Foi um pouco doloroso para depurar embora. :)

randomra
fonte
3

Haskell, 224 222 caracteres

import Data.List
p=sort.permutations
a(e:_:z)=e:a z;a z=z
[c,d]%(e:z)|any((`elem`words"012 345 678 036 147 258 048 246").take 3).p.a.reverse$e=c|1<3=[d,c]%z;_%[]='D'
main=putStr$p['0'..'8']>>=(\s->s++':':"OX"%inits s:"\n")

Infelizmente, a permutationsfunção de Data.Listnão produz permutações em ordem lexográfica. Então, eu tive que gastar 6 caracteres no gênero.

MtnViewMark
fonte
2

APL (139)

Provavelmente, isso pode ser mais reduzido, mas já foi difícil o suficiente. Acredite ou não, ele é executado em cerca de 45 segundos no meu computador (excluindo o tempo que leva para produzir tudo, quando é exibido na tela).

↑{⊃,/(,/⍕¨⍵-1),':',{1∊T←↑{∨/↑{⍵∘{⍵≡⍵∧⍺}¨↓⍉(9⍴2)⊤⎕UCS'㗀㐇㔤㑉㔑㑔'}¨↓(M∘.≥M)∧[2]M∊⍵}¨↓⍉5 2⍴0,⍨⍵:'XO'[1+</+/T]⋄'D'}⍵}¨↓{1≥⍴⍵:↑,↓⍵⋄↑⍪/⍵,∘∇¨⍵∘~¨⍵}M←⍳9

Explicação:

  • M←⍳9: Armazene em M os números de 1 a 9. Internamente, este programa usa 1..9 em vez de 0..8.
  • {... }: uma função para obter todas as permutações:
    • 1≥⍴⍵:↑,↓⍵: se o comprimento for menor ou igual a 1, retorne o argumento como uma matriz.
    • ⋄↑⍪/⍵,∘∇¨⍵∘~¨⍵: caso contrário, remova cada caractere de , obtenha as permutações disso e adicione o caractere novamente.
  • ¨↓: para cada permutação ...
  • {... }: uma função que fornece ao vencedor essa permutação:
    • ⊃,/(,/⍕¨⍵-1),':',{... }⍵: obtém a permutação como uma string, com todos os números diminuídos em 1 (para obter a saída necessária de 0..8 em vez de 1..9), seguido de dois pontos, seguido do caractere que indica o vencedor:
      • ⍉5 2⍴0,⍨⍵: separa os movimentos de X dos movimentos de O. Como O tem um movimento menor que X, esse espaço é preenchido 0, o que não é utilizado e, portanto, não influencia o resultado.
      • {... }¨↓: para a placa X e a placa O, execute a seguinte função que determina se há uma vitória em um dos nove timesteps:
        • (M∘.≥M)∧[2]M∊⍵: Gere um bitboard a partir dos números de movimentação e andesse bitboard com as strings 100000000, 110000000... 111111111para obter o estado do quadro em cada um dos nove momentos no tempo.
        • {... }¨↓: para cada um deles, execute a seguinte função:
          • ⍉(9⍴2)⊤⎕UCS'㗀㐇㔤㑉㔑㑔': obtenha os bitboards para cada possível situação vencedora
          • ⍵∘{⍵≡⍵∧⍺}¨↓: andcada estado vencedor com o bitboard atual e verifique se o estado vencedor ainda está lá
        • ∨/↑: orestes juntos, informando se há uma vitória neste bitboard
      • 1∊T←↑: crie uma matriz 9x2, com os 9 X-timesteps na primeira linha e os 9 O-timesteps na segunda linha. Guarde isso em T. Se houver um 1 nesta matriz, alguém ganhou.
      • :'XO'[1+</+/T]: Se alguém ganhou, dê 'X' ou 'O', dependendo de quem 1foi o primeiro.
      • ⋄'D': Se ninguém ganhou, dê 'D'.
  • : crie uma matriz a partir delas para que cada uma seja exibida em uma linha separada.
marinus
fonte
1

Python Ungolfed

from itertools import*
r=range
W=[[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
def c(B):
    for i in r(8):
                if B[W[i][0]]==B[W[i][1]]==B[W[i][2]]:
                        return 1
        return 0

for i in permutations('012345678',9):
    B=[]
    for j in r(9):
        B.append(-(j+1))
    k=0
    F=1
    for j in r(9):
        k=[1,0][k]
        B[int(i[j])]=k
        if c(B):
            F=0
            break
    print "".join(i),':',[['0','X'][k],'D'][F]
fR0DDY
fonte
você não precisa o segundo param empermutations
st0le
3
Por favor golf seu programa.
mbomb007
1

C ++ Ungolfed

#include<iostream>
using namespace std;
#include<algorithm>

int check(int B[])
{
        for (int i=0;i<3;i++)
                if ((B[3*i]==B[3*i+1]&&B[3*i]==B[3*i+2]) || (B[i]==B[i+3]&&B[i]==B[i+6]))
                        return 1;
        if ((B[2]==B[4]&&B[2]==B[6]) || (B[0]==B[4]&&B[0]==B[8]))
                return 1;
        return 0;               
}
int main()
{
        char c[11]="012345678";
        int B[9],i,j;
        do{
                for (i=0;i<9;i++)B[i]=-(i+1);
                for (i=0,j=1;i<9;i++,j=j?0:1)
                {
                        B[c[i]-'0']=j;
                        if (check(B))
                                break;
                }
                printf("%s:%c\n",c,i<9?j?'X':'O':'D');
        }while (next_permutation(c,c+9));
}
fR0DDY
fonte
4
Por favor golf seu programa.
mbomb007
1

Python 2.7 (237)

from itertools import*
for z in permutations('012345678'):
 k,F=0,[9]*9
 for h in z:
    F[int(h)]=k=1-k
    if any(sum(a)in(0,3)for a in(F[:3],F[3:6],F[6:],F[::3],F[1::3],F[2::3],F[::4],F[2:8:2])):break
 else:k=2
 print"".join(z)+':','OXD'[k]
Daniel
fonte