Menor compressão do tabuleiro de xadrez


39

Escreva um algoritmo ou programa que possa codificar e decodificar um tabuleiro de xadrez. O objetivo é fazer a menor representação de um tabuleiro de xadrez que possa ser usado (uma vez decodificado) para determinar todas as possibilidades de movimento de um jogador nesse turno.

A codificação deve ser capaz de mostrar:

  • De quem é a vez.
  • Se o jogador pode dominar de cada lado.
  • Se o jogador pode executar um passante e, em caso afirmativo, qual de seus peões?
  • Posições de todas as peças.

Nota importante sobre o roque: Se as brancas moverem seu rei um turno e o moverem de volta no próximo, deve ficar claro que eles não poderão se fortificar de nenhum dos lados depois disso. O mesmo ocorreria se eles movessem a torre esquerda ou direita. Embora o tabuleiro esteja visualmente no mesmo estado de dois turnos atrás, o estado do jogo mudou. Mais informações aqui: http://en.wikipedia.org/wiki/Chess#Castling

Nota importante sobre en-passant: Este também é um movimento sensível à curva. Leia as regras para mais informações. http://en.wikipedia.org/wiki/Chess#En_passant

Determine a entrada e a saída conforme necessário. Adereços principais para quem puder comprimir o máximo!

Sua pontuação é determinada no pior cenário - tamanho máximo possível em bits. Mostre como você calculou esse número e o que foi responsável. Atire no menor dos piores casos!


O que você quer dizer com "bit a bit"?
Peter Taylor

Esse é o menor código ou o mais compactado? Mais compactado é mais interessante.
Justin

Desculpe por não esclarecer. Bit a bit, no sentido de que você só pode compactá-lo se começar a representá-lo como bits, o que exigirá alguma operação bit a bit. Mau uso da minha parte. Também o código mais compactado, não o menor.
Seltzer

2
@GeekWithALife Sim, é possível ter 18 rainhas no tabuleiro ao mesmo tempo. Siga este link e clique no botão de reprodução para ver um exemplo.
ossifrage melindroso

1
@AJMansfield, isso pode ser útil para placas com cerca de 28 homens, mas calculo que 117 bits são suficientes para placas com todos os 32 homens, o que é cerca de 50 bits menos que o alvo. A complicação é que, depois de ficar abaixo de 32 homens, a promoção pode dar ao jogador mais bispos.
Peter Taylor

Respostas:


27

Mín: 12 bits
Máx:
Média:

Tinha e pensei ontem à noite que eu poderia torná-lo ainda menor.

x   Colour to play next (0 -> Black, 1-> White)
1   Only King left?

00000 Position of White King (0 -> A1 ... 63 -> H8)
00000 Position of Black King

01 00000 11111  WK:A1, BK:H2 (Black to play)
11 00000 11111  WK:A1, BK:H2 (White to play)

O resultado é um tamanho impressionante de 12 bits !

E quanto a K +1 outro tipo de peça?

x
 0
   0
     000  +Pawn
     001  +Rook   
     010  +Knight
     011  +Bishop
     100  +Queen

Existem 2 arranjos possíveis da subárvore.

   /\      /\
  +  K    K  +

Ambos resultam no mesmo tamanho de bit para todas as peças. Portanto, não faz diferença a que usamos, vou escolher o primeiro.

x
 0
  0
   000
      1011001110000000000000000000000000000000000000000000000000000000000000
(+ 000) En-Passant (if >= 2 pawn & pawn in en-passant positions)
(+ 00 ) Castlings  (if >= 1 rook)
Min: 75 bit
Max: 109 bits

Então, no King +2 outros tipos de peças

x
 0
  1
   PRBNQ
   00011  +N +Q
   00101  +B +Q
   00110  +B +N
   01001  +R +Q
   01010  +R +N
   01100  +R +B
   10001  +P +Q
   10010  +P +N
   10100  +P +B
   11000  +P +R

Existem 5 subárvores possíveis (usarei 1 e 2 para indicar qual das peças).

   /\          /\       /\         /\          /\
  /  \        /  \     /  \       /  \        /  \
 K   /\      /\   2   /\   \     1   /\      /\   \
    1  2    K  1     K  2   1       K  2    1  2   K

Portanto, precisaremos de 3 bits para codificar qual subárvore usar.

x
 0
  1
   PRBNQ
         000  Sub Tree used

Min:= 11 = Header 
       6 = 2 * 3
       4 = 1 * 4
       4 = 1 * 4
      60 = 60    Empty
      --
      85 bits

Max:=  11 = Header
        4 =  2 * 4 Kings
       48 = 16 * 3 Pawns
       12 =  4 * 3 Rook
       42 = 42 * 1 Empty
        3 =  1 * 3 En-Passant
        2 =  1 * 2 Castlings
      ---
      122 bits

Ainda fazendo a análise para mais peças

+3 Outros

x
 0
  1
   PRBNQ
         0000  Sub Tree used (of 14 possible)

+4 Outros

x
 0
  1
   PRBNQ
         000000  Sub Tree used (of 42 possible)

+5 Outros

x
 0
  1
   PRBNQ
         0000000  Sub Tree used (of 132 possible)
 (+000)
 (+00)

Max: 208?


É possível codificar todas essas subárvores em 9 bits?

Se somarmos todas as subárvores possíveis, obtemos 392 subárvores possíveis.

 1  0
 2  2
 3  5
 4  14
 5  42
 6  132
    ---
    392  <= 2^9

Usando Freq ID

Uma vez que existem 164603 frequências de peças únicas .

Log2( 164603) = 17.3286110452
             ~ 18 bits

0
 0000 0000 0000 0000 00  Freq ID

(+000) (+00) Rolagem

Máx: = 204 bits


rev 3

Mín: 82 Máx: 199 Média: 160

Finalmente, comecei a fazer algumas análises para encontrar o tamanho máximo de bit. Com codificação huffman ideal para cada uma das frequências de peça únicas .

               0   Player
              00  Castling
               0  En-Passant Possible
            ?000  En-Passant column (include if En-Passant Possible = 1
  0000 0000 0000  Tree Encoding ID
[Board Encoding]  Between 66 .. 180 bits 

Observe que esse é o pior tamanho possível, que a coluna En-Passant bits se o número de peões for maior que um. Independentemente das cores e posição dos peões, existe o potencial de algumas placas serem 3 bits menores.

Além disso, existem apenas 144 tamanhos diferentes (pior caso) para o tamanho da placa.


75 - 216 bits (v2) v1 O tamanho mínimo é de 98 bits (12,25 bytes), apenas os dois reis da placa.

O tamanho máximo é de apenas 216 bits (27 bytes). No improvável: -

  9 x Queens
  1 x King
  2 x Rooks
  2 x Knights
  2 x Bishops
on each side.

Em média, o tamanho será de cerca de 157 bits (19.625 bytes).

Peças

Para codificar a placa, estou usando um esquema de codificação de árvore binária. Um quadrado vazio é o mais frequente entre 32 e 62 aparições. A seguir, estão os peões, e as Torres, Cavaleiros, Bispos e os menos frequentes são a Rainha e o Rei.

0 - left node
1 - righ node

     /\
    e  \    e:= Empty Square
      B/\W  B:= Black ; W:= White
      /  \
     /    \
    /      \
   /\      /\
  p  \    p  \  p:= Pawn
     /\      /\
    /  \    /  \
   /\  /\  /\  /\
  r  b n \ r b n \  r:= Rook; b:= Bishop; n:= Knight
         /\      /\ 
        q  k    q  k  q:= Queen ; k:= King

O quadro inicial pode ser codificado em apenas 166 bits (20.75 bytes)

  A     B     C      D      E     F     G     H
-----+-----+-----+------+------+-----+-----+------+
10100 10101 10110 101110 101111 10110 10101 10100 | 8 
  100   100   100    100    100   100   100   100 | 7
    0     0     0      0      0     0     0     0 | 6
    0     0     0      0      0     0     0     0 | 5
    0     0     0      0      0     0     0     0 | 4
    0     0     0      0      0     0     0     0 | 3
  110   110   110    110    110   110   110   110 | 2
11100 11101 11110 111110 111111 11110 11101 11100 | 1

Para indicar quem se move, é preciso apenas um bit

0-> Black , 1-> White

A rolagem pode ser codificada em 4 bits.

 B  W
LR LR
00 00

Então, eu uso 171 bits (21.375 bytes)

O En-Passe pode ser codificado em apenas 16 bits (2 bytes)

Então, no total, isso é 187 bits (23.375 bytes).

Layout

  bits    Encodes
 0 -  15  En-Passe
16 -  19  Castling
      20  Move 
21 -  23  Unused
24 -> ..  Board

Ainda não escreveu nenhum código.

Observe que 3 dos bits não são utilizados. Portanto, o máximo é 213bits .


Possíveis melhorias

1) Reduzido o formulário do bloco de cabeçalho de 24 para 8 bits (com sugestão de Peter Taylor)

0 - 2 En-Passant
    3 Move
4 - 7 Castling
8 ... Board Pieces 

2) Cabeçalho de comprimento variável

Um pequeno cabeçalho fixo de 4 bits

0 0 0 0
| | | |
| | | +-> En-Passant Block Present?
| | | 
| | +---> Pawns on board?
| |
| +-----> Castling still possible?
|                
+-------> Who's move? 0-Black 
                      1-White

Próximo bloco de bits adicionais (se ainda é possível fazer rapel)

00 00
|| ||
|| |+-> White Castle Right
|| +--> White Castle Left
||
|+----> Black Castle Right
+-----> Black Castle Left

Próximo bloco de bits adicionais (se houver peões)

000--> En-Passant column Position

Então agora eu tenho um cabeçalho de comprimento variável de 4 a 11 bits


3) Use um esquema de codificação diferente, dependendo das peças restantes no quadro.

Alterando a codificação em árvore, dependendo de quais peças estão no quadro e da frequência.

Uma codificação possível para um estado final do jogo (sem peões)

        /\            
       e /\           
  Black /  \ White
       /    \
      /      \
     /        \       
    /\        /\
   /  \      /  \     
  /   /\    /   /\
 /\  / /\  /\  / /\   
r b n q k  r b n q k

Que é de cerca de ~ 4 bits por peça.

Que tipo de peças estão presentes no quadro?

RBNQK Permutation
11111 (11111)

Permutação é comprimento variável de 0 a 5 bits. Se apenas um tipo de peça for deixado, não o inclua.

Qual permutação dessas peças usar na árvore? Este é o fatorial do número de peças no exemplo acima, é de 5 peças, para 120 possíveis permutações que podem ser codificadas.

 #    !  bit 
 6  720  10  (If pawn included)
 5  120   6
 4   24   5
 3    6   3
 2    2   1  Don't include as of equal size.
 1    1   0  Don't include as its not needed.

Lembre-se de que existem bits de adição para os quadrados e cores vazios.


Exemplos

Vamos dar um exemplo de apenas QK restante

RBNKQ
00011

  /\
 s  \
    /\
  B/  \W
  /\  /\
q  k q  k

101 100  0 x 60 110 111 ==> 60 + (2 x 6) = 60 + 12 = 72 bits for the board

0000 00011 Header ==> 9 bits

Total de 81 bits


Vamos dar e exemplo de apenas reis restantes

 RBNQK
 00001 

  /\
 s  k
   / \
  B   W

 10 0 0 0 0 0 0 0   K... ....
  0 0 0 0 0 0 0 0   .... ....
  0 0 0 0 0 0 0 0   .... ....
  0 0 0 0 0 0 0 0   .... ....
  0 0 0 0 0 0 0 0   .... ....
  0 0 0 0 0 0 0 0   .... ....
  0 0 0 0 0 0 0 0   .... ....
  0 0 0 0 0 0 0 11  .... ...k

Coloque tudo junto

 header  4   0 0 0 0
 pieces  5   0 0 0 0 1
 perm    0   - - - - - -
  board 66   10 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 0
              0 0 0 0 0 0 0 11

Então eu calculo a menor codificação para placa em 75bits (9 bits e 3 bits)

Ainda não foi calculado como esse esquema de codificação afeta o tamanho máximo.


Melhoria 4

Reduza o número de bits para rolagem para apenas 2 bits. Apenas jogue para o jogador que é a vez.

 0 Castling possible (from header block)
 LR 
 00

Pensando nisso, talvez seja melhor incluir apenas os 2 bits dentro do bloco de cabeçalho.


Você não precisa de 16 bits para en passant. No máximo, um peão se moveu no último turno, portanto, quatro bits são suficientes (por exemplo, 1111para "nenhum en passant possível" ou a coluna como um número binário).
Peter Taylor

Por que os peões conseguem uma posição melhor em uma árvore? No caso comum, são mais comuns, mas, em casos extremos, R / B / N pode aparecer 10 vezes.
precisa saber é

@ PeterTaylor, na verdade 3 bits são suficientes para en passant. Se você contar apenas colunas com um peão preto da 5ª posição (assumindo movimento branco), 8 se tornará inválido.
precisa saber é

1
Observe que seu pior caso não é realmente possível. A promoção é impossível sem capturas (é necessária pelo menos uma captura por 2 promoções).
ugoren

2
Nota para codificar 64 posições (para rei branco ou preto), você precisa de 6 bits (2 ** 6 = 64).
usar o seguinte código

17

192 bits (pior caso)

Aqui está um esquema de armazenamento muito simples que deve lidar com promoções arbitrárias de peões e nunca exige mais do que 64 + 4 × 32 = 192 bits:

  • Os primeiros 64 bits armazenam um painel de bits que indica onde estão as peças (mas não o que são). Ou seja, armazenamos um bit para cada quadrado do tabuleiro de xadrez (começando no quadrado a1, depois b1, c1 etc. até o quadrado h8), de modo que um quadrado vago seja representado por 0 e um quadrado ocupado por 1.

  • Em seguida, para cada um dos quadrados marcados como ocupados no bitboard, armazenamos uma mordidela de 4 bits que codifica a peça nesse quadrado. O primeiro dos quatro bits codifica a cor da peça (0 = branco, 1 = preto), enquanto os três bits restantes codificam o tipo da peça:

    +-----+-----+-----+-----+
    |Black|   Piece Type    |
    +-----+-----+-----+-----+
       4     3     2     1    Bits
    

    Tipo de peça

    0 = peão (normal)
    1 = torre (normal)
    2 = cavaleiro
    3 = bispo
    4 = rainha
    5 = rei (do jogador a seguir)
    6 = rei (do outro jogador)

    Observe as duas codificações do rei, usadas para determinar qual turno do jogador ele deve se mover. (De fato, como sempre existem dois reis no tabuleiro, permitindo quatro combinações dos códigos 5 e 6, poderíamos facilmente codificar um segundo bit de informação aqui.)

    Black Type Description
    +----+----+--------------------------------+
    |  0 | 5  | White King; White to move next |
    +----+----+--------------------------------+
    |  0 | 6  | White King                     |
    +----+----+--------------------------------+
    |  1 | 5  | Black King; Black to move next |
    +----+----+--------------------------------+
    |  1 | 6  | Black King                     |
    +----+----+--------------------------------+
    

    Para codificar as informações extras necessárias para as regras en passant e castling, introduzimos um tipo de peça adicional, que indica um peão ou uma torre, dependendo da linha em que aparece:

    7 (nas linhas 1 e 8) = uma torre que nunca se moveu, e cujo rei também nunca se moveu e, portanto, é elegível para jogar
    7 (nas linhas 4 e 5) = um peão que acabou de avançar dois quadrados e pode, portanto, ser capturado en passant

Juntando tudo:

     Hex Description
    +---+---------------------------------------------+
    | 0 | White Pawn (normal)                         |
    | 1 | White Rook (has moved)                      |
    | 2 | White Knight                                |
    | 3 | White Bishop                                |
    | 4 | White Queen                                 |
    | 5 | White King; White to move next              |
    | 6 | White King                                  |
    | 7 | White Rook (pre castle) / Pawn (en Passant) |
    | 8 | Black Pawn (normal)                         |
    | 9 | Black Rook (has moved)                      |
    | A | Black Knight                                |
    | B | Black Bishop                                |
    | C | Black Queen                                 |
    | D | Black King; Black to move next              |
    | E | Black King                                  |
    | F | Black Rook (pre castle) / Pawn (en Passant) |
    +---+---------------------------------------------+

O número total de bits necessários para codificar o estado da placa é, portanto, 64 + 4 × # de peças a bordo. Como nunca pode haver mais de 32 peças no quadro, o comprimento máximo dessa codificação é de 192 bits.

Por exemplo, usando a codificação descrita acima, o estado inicial da placa seria codificado como (espaço em branco inserido para facilitar a leitura):

1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111
0111 0010 0011 0100 0101 0011 0010 0111 0000 0000 0000 0000 0000 0000 0000 0000
1000 1000 1000 1000 1000 1000 1000 1000 1111 1010 1011 1100 1110 1011 1010 1111

ou, em hexadecimal:

FFFF 0000 0000 FFFF 7234 5327 0000 0000 8888 8888 FABC EBAF

2
"peão ​​que acabou de avançar dois quadrados" e "torre que nunca se moveu" poderiam compartilhar o mesmo slot de estado, pois são mutuamente exclusivos, dependendo da linha em que estão. O estado extra-livre pode ser usado para codificar "rei da cor de quem é a vez"; você deve conseguir se livrar dessa parte danificada.
FireFly

Você também pode economizar um pouco, armazenando apenas 63 bits para o painel de bits e deduzindo o último bit do número de homens codificados. (Não está claro para mim se isso é trapaça ou não, porque requer codificação externa do comprimento da sequência de bits). E se você abandonar os estados 6 e 7 para os homens, precisará codificar até 6 ^ 32, o que leva 82,7 bits; arredondando para 83, economizando 13 bits nos estados 6 e 7, e você pode codificar a mesma informação em apenas 8 bits.
Peter Taylor

Obrigado, @FireFly! Eu implementei sua sugestão. (A sugestão de Peter Taylor é ainda mais eficiente, é claro, mas ainda não a usei porque gosto da codificação binária simples do esquema atual. Você sempre pode enviá-la como uma entrada separada ...)
Ilmari Karonen

Ok - isso é um pouco complicado. Mas me ouça. Se você apenas acertar o bit de 1 bit em um indicador de turno, poderá substituir king por turno por uma peça que eu chamo de peão1. Mude o peão para o peão0. Agora, sempre que houver um peão (não vulnerável a passantes) - você também obterá um pouco de informação na próxima peça (um 0 para peão0 ou 1 para peão1). Como existem 16 peões, você ganha 16 bits a menos 1 no indicador de mudança de direção. Sempre que houver um peão vulnerável a passantes, você deverá adicionar um pouco depois. Mas, como deve acontecer imediatamente, seus ganhos mínimos são de 14 bits.
user5957401

Você também pode fazer algo semelhante com bispos. Suponha que você tenha um bispo que não esteja em uma 'zona especial' (os 10 pontos nos cantos e a linha central do lado) esteja marcado como especial. Porque você conhece sua localização - você sabe que é um bispo. Agora você tem dois bispos e poderia dar a cada um um 0 ou 1 na próxima peça. Isso dá mais 4 bits - mas o pior caso tem bispos em todas as zonas especiais, e nenhum ganho.
user5957401

14

Pior caso de 160 bits

Depois de postar minha resposta anterior em 22 bytes, comecei a me perguntar se conseguiríamos chegar a 21 bytes. No entanto, quando vi os incríveis 166 bytes de Peter Taylor, pensei: "Espere, parece que cinco palavras de 32 bits podem ser possíveis!"

Então, depois de muita reflexão, eu pensei nisso: 159.91936391 bytes (um ajuste bastante apertado!) Esse nível de compactação precisaria de um programa bastante complicado, mas eu pensei em como fazê-lo funcionar em tempo razoável.

Este será um post longo, portanto, tenha paciência comigo, publicarei o que puder hoje e adicionarei alguns bits de código em breve.

Então, aqui está como fazer isso:

En Passant e roque codificados por posições ilegais (0 bits)

En Passant

Como mencionado em outras respostas, há no máximo 5 quadrados possíveis nos quais um peão vulnerável a um passante pode ficar. Estes são os quadrados próximos aos peões do jogador em que é a vez.

Para codificar isso, o peão vulnerável a passante é trocado pelo que estiver em um dos quadrados na primeira ou na última linha. Pode ser um homem ou um quadrado vazio. Isso produz uma posição ilegal, pois os peões não podem estar nessas linhas. O decodificador deve retornar o peão à sua posição correta, extraindo as informações passantes.

Para que isso não interfira com a codificação de rolagem, é importante que os quadrados em que os reis estão no início do jogo não sejam perturbados e que o procedimento de codificação passante não coloque os reis próximos um do outro, o que seria uma posição ilegal do rei. Para satisfazer o segundo desses pontos, o codificador tem duas opções para qual quadrado ele troca o peão passante. O quadrado de primeira escolha para cada um dos cinco peões é A8, B8, C8, G8, H8. Segunda opção: A1, B1, C1, G1, H1.

Castling

Um rei que tem permissão de castelo está por definição, ainda em sua praça inicial. Com o rei branco em seu quadrado inicial, há um total de 63 quadrados onde o rei preto pode permanecer, 58 dos quais são legais (ele não pode se mover ao lado do rei branco porque se colocaria em xeque). Se o rei branco tem permissão de castelo, ele também pode castelo com sua torre esquerda, sua torre direita ou ambas. Existem, portanto, 3x58 = 174 possibilidades em que o rei branco pode dominar, outros 174 em que o rei preto pode dominar e mais 3x3 = 9 em que ambos podem dominar, um total de 357.

Existem 420 arranjos ilegais dos dois reis em quadrados adjacentes: 3x4 = 12 quando o rei branco está no canto, 5x24 = 120 quando ele está no limite e 8x36 = 288 quando ele está em outro quadrado. Portanto, existem facilmente posições ilegais suficientes para codificar todas as possibilidades possíveis de rolagem.

Se pelo menos um rei puder castigar, o codificador procurará os dados de castelos e os dados posicionais daqueles reis que não podem castigar em uma tabela (ou, alternativamente, use um algoritmo que não especificarei aqui) e produzirá um código ilegal. posição dos dois reis. Trocaria então os reis com o que acontecesse nessas praças.

É importante que isso seja codificado e decodificado antes do passante, caso contrário, existem algumas interferências em potencial.

Comparação

Até agora, não usei bits! Olhando para a resposta de Peter, ainda tenho o seguinte para codificar:

Whose turn is it?                                   1.000 bits
Which squares are occupied by men of which colour? 91.552 bits 
Subtotal                                          *92.552 bits* 
For the two colours, which men and which order?   *68.613 bits* 
GRAND TOTAL                                       161.165 bits

Este é o pior caso de 29 homens (veja a resposta de Peter.) Abaixo mostrarei como faço uma melhoria marginal (pelo menos no caso de 29 homens) em ambos os pontos marcados em **.

Quais quadrados estão ocupados / de quem é a vez?

A maneira fácil de codificar quais quadrados são ocupados é com uma grade de 64 bits. Isso também nos diz quantos quadrados estão ocupados. No entanto, é um pouco de desperdício, porque não é possível haver mais de 32 quadrados ocupados. Minha solução é usar 1 para codificar para os quadrados ocupados quando for a vez das Brancas e 0 para codificar para quadrados ocupados quando for a vez das Pretas. Agora todas as combinações são usadas e não há desperdício.

Assim, economizamos um pouco para armazenar o turn: menos de 32 1, é a vez das brancas, mais de 32 1, é a vez das pretas. O único caso ambíguo é quando todos os homens estão no quadro e há 32 1 e 32 0. Portanto, um bit extra é necessário apenas para este caso. Como não pode haver promoções até que uma captura ocorra, esse bit extra não afeta o pior caso geral (o que ocorre com 3 homens capturados e 29 restantes).

Cor dos homens ocupando as praças

Sabemos do exposto quantos homens existem. O extrato a seguir do triângulo de Pascal conta quantas possibilidades existem para as diferentes distribuições de preto e branco. Por exemplo, para 3 homens, as possibilidades são: 3 homens negros (1 permutação) 2 pretos, 1 branco, (3 permutações), 1 preto, 2 brancos (3 permutações), 3 brancos (1 permutação). O total é 2 3 = 8. Em geral, para os números mais baixos de homens existem 2 n possibilidades. No entanto, todas as possibilidades de preto e branco são ilegais (pelo menos o rei de cada lado deve estar no tabuleiro), portanto o número real de permutações legais é 2 n -2 (ignore os 1s no triângulo Pascal).

Para mais de 16 homens no total, há uma restrição adicional, pois não pode haver mais de 16 homens de cada cor no quadro. Portanto, quando todos os 32 homens estão no quadro, deve haver 16 de cada um e o número total de possibilidades é 601080390, que é um pouco menor que 2 32 .

1   1    1    1      1     1      1       1       1        1        1         1         1         1          1          1          1 
1   2    3    4     5      6      7       8       9       10       11        12        13        14         15         16         17
1   3    6   10    15     21     28      36      45       55       66        78        91       105        120        136        153
1   4   10   20    35     56     84     120     165      220      286       364       455       560        680        816        969
1   5   15   35    70    126    210     330     495      715     1001      1365      1820      2380       3060       3876       4845
1   6   21   56   126    252    462     792    1287     2002     3003      4368      6188      8568      11628      15504      20349
1   7   28   84   210    462    924    1716    3003     5005     8008     12376     18564     27132      38760      54264      74613
1   8   36  120   330    792   1716    3432    6435    11440    19448     31824     50388     77520     116280     170544     245157
1   9   45  165   495   1287   3003    6435   12870    24310    43758     75582    125970    203490     319770     490314     735471
1  10   55  220   715   2002   5005   11440   24310    48620    92378    167960    293930    497420     817190    1307504    2042975
1  11   66  286  1001   3003   8008   19448   43758    92378   184756    352716    646646   1144066    1961256    3268760    5311735
1  12   78  364  1365   4368  12376   31824   75582   167960   352716    705432   1352078   2496144    4457400    7726160   13037895
1  13   91  455  1820   6188  18564   50388  125970   293930   646646   1352078   2704156   5200300    9657700   17383860   30421755
1  14  105  560  2380   8568  27132   77520  203490   497420  1144066   2496144   5200300  10400600   20058300   37442160   67863915
1  15  120  680  3060  11628  38760  116280  319770   817190  1961256   4457400   9657700  20058300   40116600   77558760  145422675
1  16  136  816  3876  15504  54264  170544  490314  1307504  3268760   7726160  17383860  37442160   77558760  155117520  300540195
1  17  153  969  4845  20349  74613  245157  735471  2042975  5311735  13037895  30421755  67863915  145422675  300540195  601080390

O número de possibilidades pode ser encontrado somando as "linhas" deste extrato do triângulo de pascal (com o que quero dizer as diagonais NE-SW da tabela, porque eu girei o triângulo 45 graus no sentido anti-horário para uma apresentação conveniente. para codificar o turno, os quadrados ocupados e a cor dos homens são, portanto, os seguintes:

Até 25 homens: pouco menos de 64 anos (número de homens)
Para mais de 25 homens:

men permutations  bits required  occupied sq+turn   
    of colours                   (bits required)  total bits
26   55791790     25.7335495      64              89.7335495
27  100960110     26.58921015     64              90.58921015
28  175844430     27.3897244      64              91.3897244
29  290845350     28.115677       64              92.115677   
30  445962870     28.73234836     64              92.73234836
31  601080390     29.16298271     64              93.16298271
32  601080390     29.16298271     65              94.16298271

Para as duas cores, quais homens e em que ordem?

De acordo com as respostas anteriores, nenhum peão pode ser promovido até que uma captura ocorra, porque cada peão é bloqueado por um peão da cor oposta na mesma coluna. A resposta de Peter considerou (como limite superior) que toda captura poderia levar a uma promoção para o lado que estava sendo capturado e duas para a captura lateral. No entanto, podemos dividir isso em vários casos:

  1. O peão preto captura o peão branco: agora o peão de captura está livre para promover, pois ele está agora em uma coluna diferente. Seu colega na mesma coluna também pode promover. O peão preto na coluna original do peão branco também pode ser promovido. Este é o único caso que permite 3 promoções.

  2. O peão preto passa pelo peão branco na coluna adjacente e depois captura a peça branca (exceto o peão) por trás. Isso permite que o peão de captura e o peão branco que estava na coluna original sejam promovidos. Uma promoção para cada lado.

  3. O peão branco é capturado por peça (exceto o peão.) Isso normalmente permitiria uma promoção apenas para as pretas. A única exceção é quando ele libera uma formação de peão bloqueada que já foi causada por várias capturas que movem peões para a mesma coluna.

Portanto, como caso base, podemos considerar que cada captura permite uma promoção para os dois lados. No caso de o homem capturado ser um peão, pode haver uma promoção adicional para o lado da captura.

Eu escrevi um programa semelhante ao de Peter. É um pouco mais grosseiro, mas tem uma adição importante: pode calcular o número de permutações possíveis quando um jogador começa com menos do que os 8 peões normais. Aqui estão alguns dados produzidos pelo programa:

Max promotions   0            1            2             3             4              5 
8 PAWNS 
13 men    18725850    146911050    567991710    1373480394    2297173164     2902775304
14 men    36756720    339459120   1555313760    4501448952    9021804792    13325103792
15 men    60810750    660810150   3555401850   12144582450   28834205400    50030580600
16 men    64864800    843242400   5383778400   21810428640   61514893440    1.26476E+11
7 PAWNS                         
13 men    17760600    141003720    546949260    1321302840    2200401060     2761730400
14 men    30270240    287567280   1331890560    3852728880    7641553920    11068817760
15 men    32432400    372972600   2075673600    7209001800   17135118000    29315286000
6PAWNS                          
13 men    14054040    114594480    447026580    1069488420    1739577840     2113185360
14 men    15135120    151351200    718918200    2087805720    4073028960     5697051360                         
5 PAWNS                         
13 men     6486480     55135080    217297080     510630120     794233440      910235040

Podemos ver que, para um caso como 8 peões, 15 homens, 0 promoções, o número de permutações é apenas ligeiramente menor do que para 8 peões 16 homens, 0 promoções. No entanto, se considerarmos um caso como 7 peões, 15 homens, 0 promoções (o que é o mesmo que considerar que o homem capturado era definitivamente um peão), obteremos cerca da metade do número de permutações.

Portanto, para o caso de preto ter 16 homens e branco 15, podemos considerar uma estimativa superior de 2 promoções para preto e uma promoção para branco:

5383778400 x 660810150 = 3.55766E+18 possibilities

No entanto, podemos fazer melhor se procedermos da seguinte maneira.

A. Considere uma promoção para Black and White, assumindo que o homem que White perdeu pode ser de qualquer tipo:

843242400 x 660810150 = 5.57223E+17 possibilities

B. Considere as possibilidades adicionais para as pretas se ele tiver duas promoções, multiplicadas apenas pelas possibilidades para as brancas nas quais ele perdeu um peão.

(5383778400-843242400) x 372972600 = 1.6935 E+18 possibilities.

Somando esses dois, obtemos 2.25072E + 18, que é um número menor que 3.55766E + 18. Todas as possibilidades para até 3 capturas (29 homens restantes) estão listadas abaixo.

(Promotions, Pawns lost) possibilities

BLACK 16 MEN, WHITE 15 MEN. ESTIMATE   3.55766E+18 = 2^61.62563249
(1,0)   843242400 x (1,0)  660810150 = 5.57223E+17
(2,0)  4540536000 x (1,1)  372972600 = 1.6935 E+18
                               TOTAL   2.25072E+18 = 2^60.96509144


BLACK 16 MEN, WHITE 14 MEN. ESTIMATE   9.5675 E+19 = 2^66.3747752
(2,0)  5383778400 x (2,0) 1555313760 = 8.37346E+18
(3,0) 16426650240 x (2,1) 1331890560 = 2.18785E+19
(4,0) 39704464800 x (2,2)  718918200 = 2.85443E+19
                               TOTAL   5.87962E+19 = 2^65.67235739


BLACK 16 MEN, WHITE 13 MEN. ESTIMATE   2.69447E+20 = 2^67.86856193
(3,0) 21810428640 x (3,0) 1373480394 = 2.99562E+19
(4,0) 39704464800 x (3,1) 1321302840 = 5.24616E+19
(5,0) 64960896000 x (3,2) 1069488420 = 6.94749E+19
(6,0) 69702272640 x (3,3)  510630120 = 3.55921E+19
                               TOTAL   1.87485E+20 = 2^67.34533572


BLACK 15 MEN, WHITE 15 MEN. ESTIMATE   1.47491E+20 = 2^66.99918768
(2,0)  3555401850 x (2,0) 3555401850 = 1.26409E+19
(2,1)  2075673600 x (3,0) 8589180600 = 1.78283E+19
(3,0)  8589180600 x (2,1) 2075673600 = 1.78283E+19
(3,1)  5133328200 x (3,1) 5133328200 = 2.63511E+19
                  TOTAL BOTH COLUMNS   7.46486E+19 = 2^66.01674923


BLACK 15 MEN, WHITE 14 MEN. ESTIMATE   4.51366E+20 = 2^68.61286007      
(3,0) 12144582450 x (3,0) 4501448952 = 5.46682E+19
(3,1)  7209001800 x (4,0) 4520355840 = 3.25873E+19
(4,0) 16689622950 x (3,1) 3852728880 = 6.43006E+19
(4,1)  9926116200 x (4,1) 3788825040 = 3.76083E+19
(5,0) 21196375200 x (3,2) 2087805720 = 4.42539E+19
(5,1) 12180168000 x (4,2) 1985223240 = 2.41804E+19
                  TOTAL BOTH COLUMNS   2.57599E+20 = 2^67.80368692

Portanto, para o pior caso de um lado com 15 homens e o outro com 14 homens, precisamos de 67,804 bits.

Adicionando isso aos 92.116 bits necessários para especificar quais quadrados e quais cores, obtemos um total de 67,804 + 92,116 = 159,92 bits.


1
Muito obrigado a @Einacio por alterar minhas vírgulas decimais para pontos decimais. Fiz muitas das minhas tabelas no Excel em um computador espanhol, e postar isso foi um grande trabalho; portanto, corrigir isso foi algo que deixei para mais tarde. Como eu disse, ainda não terminei este post, adicionarei meu programa de contagem de permutações e alguns fragmentos de código sobre codificação / decodificação quando tiver tempo. PS. Eu não tinha idéia que tantas pessoas estavam lendo este :-)
Nível River St

no final, você conseguiu digitar bytes em vez de bits, o que você quis dizer com isso, que pode causar uma certa confusão aos leitores
#

13

Pior caso de 177 bits

Esse algoritmo, embora dificilmente simples, fornece o pior cenário de 177 bits (184b = 23B na prática), 13b (16b = 2B) no melhor cenário quando restam apenas dois reis.

Bit     Description
  1     Turn (0=white 1=black)
  2-  7 White king position (2-4=letter, 5-7=number)
  8- 13 Black king position (8-10=letter, 11-13=number)
 14- 75 Which squares contain pieces (skipping the 2 king squares, so only 62)
        Ordered a1-h1,a2-h2,(...)
 76-105 Which color owns the square with their piece (0=white, 1=black)
        If there's LESS than 30 pieces (apart from kings), this area is
        smaller
106-end Square data

Square data has the following system:
Every square gets assigned a number which determines piece. Number is:
0 Queen
1 Rook
2 Bishop
3 Knight
4 Pawn OR allowed-castle rook depending on square
5 Pawn subject to potential enpassant

The first bits (max 13) is the potential enpassant slots from A-H, determined
from data of 1 + 14-105 for which of the squares has a piece, and which color
owns the piece and whose turn it is. For example, if turn is White (bit 1 is
0), all pieces on row 5 which is Black owned (determined from 14-105 metadata)
and has at least 1 adjacant (on the same row) square owned by White, is
explained in A-H order. A base 6 number is used which is converted to binary
for the storage. On reading, it's converted and read A-H according to the
numbers above (4 is obviously pawn in this case).
The second amount of bits takes care of the 1st and 8th row (not corners!)
in b1-g1,b8-g8. These only take up 2 bits since 4 or 5 is never needed
(pawn on 1st or 8th is invalid).
The third amount of bits takes care of the rest of the board, in the following
order: a1,h1,a2-h2,a3-h3,a4-h4,a5-h5,a6-h6,a7-h7,a8,h8 (skipping the
"enpassant" slots), in base 5 (since piece ID 0-4 are the only used) converted
to binary.

Best case: 13 bits (bit 1 for turn, bit 2-12 for kings)
Worst case: 177 bits
* 32 pieces with kings
* 5 viable enpassant pawns
* No pieces at 1st or 8th row (except if kings+rooks are at initial posions
whether or not they can castle)
In this case, the space as following:
  1   bit   turn
+ 12  bits  king positions
+ 62  bits  which squares have pieces
+ 30  bits  color of pieces
+ 13  bits  enpassant area
+ 0   bits  initial rows area
+ 59  bits  the rest of the area
= 177 bits  total

Potential optimizations but not really worth it IMO:
* Decrease average by make corners 2 bits as well if kings aren't at e1/e8
* Alter reading order to read b1-g1,b8-g8 last - decreases worst case to
  176 bits if the "which squares have pieces" area is cut off if 30 existing
  pieces has been defined already. Would actually save 8 bits on file but meh

Muito agradável. Você pode tornar isso ainda mais eficiente, substituindo os bits 14-105 (92 bits) por uma codificação baseada em coeficientes multinomiais. sum_{i=0}^{15} sum_{j=0}^{15} 62! / (i! j! (62-i-j)!) < 2^87.45.
Peter Taylor

A única coisa que eu mudaria é criar uma versão bastante mais simplificada para a área abrangente. Por exemplo: se você codificar as 30 partes na base 5 e houver um máximo de 5 posições adjacentes, poderá ter 5 ^ 31 <2 ^ 72. O mesmo que se você os dividisse em enpassant (13) e não enpassant (59), mas sem a complexidade extra.
Alin Stoian

Fazer isso usaria 1 bit extra. A razão é que pode (no pior dos casos) haver cinco possibilidades iminentes, mas eu ainda preciso declarar a possibilidade de "não iminente", ou seja, um sexto estado. Nesse caso, o 1 bit extra passaria a declarar possível o enpassante (e com essa abordagem eu poderia usar uma abordagem ainda mais simples com a codificação das 30 partes que pulam o bloco enpassant e usar 3 bits separadamente para a verificação do enpassant, o que seria também levam ao uso de +1 bit). A 5ª linha a seguir permitiria 5 possíveis enpassantes (turno de White): BWBBWBBW
FIQ

sim, você está certo.
Alin Stoian

7

166 bits

  • 1 bit: de quem é a vez?
  • 2bits: quais opções de rolagem estão abertas? (Nota: lendo atentamente a pergunta, é necessário apenas registrar as opções de boliche para o jogador em que turno é).
  • lg 6 ~= 2.585bits: quais opções en passant estão abertas? (Veja minha outra resposta)
  • lg sum_{i=1}^{16} sum_{j=1}^{16} 64! / (i! j! (64-i-j)! = lg 3629590441720924477681996172 ~= 91.552 bits: quais quadrados são ocupados por homens de que cor?
  • Na pior das hipóteses, lg 451366131803622235200 ~= 68.613para indicar quais homens e em que ordem (veja abaixo)

Usando codificação aritmética (já que a cada passo estamos aplicando uma distribuição uniforme), podemos obter ceil(3 + 2.585 + 91.552 + 68.613) = 166bits.

A codificação para os homens: dado que sabemos quantos homens de uma determinada cor existem, podemos enumerar facilmente todas as distribuições / multisets possíveis de homens (por exemplo, com 5 homens, podemos ter um rei, uma rainha, duas torres e uma Peão) e então podemos considerar todas as permutações possíveis de cada distribuição.

No entanto, podemos melhorar ainda mais, levando em consideração as interdependências. Só estou fazendo isso em um nível muito básico: quantas promoções possíveis? Um peão só pode ser "aprovado" e capaz de promover de três maneiras: captura e, portanto, move-se para uma coluna diferente; ou seu peão oposto captura e então se move para uma coluna diferente; ou seu peão oposto é capturado. Assim, uma captura para branco cria potencialmente dois peões passados ​​para branco e um para preto.

Podemos criar uma tabela parcial dos limites superiores nas promoções:

(Max white promos, max black promos):

           White men
           16      15      14      13
Black men
       16  (0, 0)  (1, 2)  (2, 4)  (3, 6)
       15  (2, 1)  (3, 3)  (4, 5)  (5, 7)
       14  (4, 2)  (5, 4)  (6, 6)  (7, 8)
       13  (6, 3)  (7, 5)  (8, 7)  (8, 8)

Também podemos calcular o número de permutações, considerando que um jogador tem Nhomens e não mais que Ppeões promovidos:

Num of permutations (cumulative):
    max promotions: 0              1              2              3              4              5              6              7              8
 1 men              1              1              1              1              1              1              1              1              1
 2 men             10             10             10             10             10             10             10             10             10
 3 men             72             75             75             75             75             75             75             75             75
 4 men            436            496            500            500            500            500            500            500            500
 5 men           2305           3025           3120           3125           3125           3125           3125           3125           3125
 6 men          10746          17106          18606          18744          18750          18750          18750          18750          18750
 7 men          44170          88795         106260         109179         109368         109375         109375         109375         109375
 8 men         159832         415360         575240         619200         624744         624992         625000         625000         625000
 9 men         509841        1721961        2884815        3398769        3504735        3515301        3515616        3515625        3515625
10 men        1447200        6258240       13063080       17697780       19260180       19510320       19530840       19531230       19531240
11 men        3706065       20021265       52183395       85007571      102173181      106786581      107369592      107409918      107410281
12 men        8678340       57101220      183088620      364510476      509818716      570620556      584017632      585352152      585430164
13 men       18725850      146911050      567991710     1373480394     2297173164     2902775304     3107861328     3143928216     3146014014
14 men       36756720      339459120     1555313760     4501448952     9021804792    13325103792    15664512864    16283899632    16360920576
15 men       60810750      660810150     3555401850    12144582450    28834205400    50030580600    66655789200    73588394880    74576231730
16 men       64864800      843242400     5383778400    21810428640    61514893440   126475789440   196178062080   240747386880   253686232800

Combinando os dois, podemos obter o número de bits necessário para especificar as duas permutações, considerando o número de homens de ambos os lados:

           White men
           16      15      14      13      <13
Black men
       16  51.902  61.626  66.375  67.868  <=67.009
       15  --      67.000  68.613  67.534  <=65.243
       14  --      --      67.734  65.480  <=63.055
       13  --      --      --      63.102  <=60.676

Se não estiver nesta seção da tabela, podemos apenas assumir que ambos os lados têm até 8 promoções e ainda estamos indo melhor do que o pior caso, que é de 68.613 bits quando um tem 14 homens e o outro 15.

Observe que isso ainda está longe de ser uma representação perfeita, pois permite muitas posições ilegais.

Código para o cálculo da tabela de permutação:

import java.util.*;

public class ChessCombinatorics {
    public static void main(String[] args) {
        long[] f = new long[17];
        f[0] = 1;
        for (int i = 1; i < 17; i++) f[i] = i * f[i-1];

        // Indexed by num promotions, then total num men.
        long[][] distribs = new long[9][17];
        long[][] perms = new long[9][17];

        for (int promotedPawns = 0; promotedPawns < 9; promotedPawns++) {
            Map<Integer, Map<String, Long>> numCases = new HashMap<Integer, Map<String, Long>>();
            for (int i = 1; i < 17; i++) numCases.put(i, new HashMap<String, Long>());

            for (int extraQ = 0; extraQ <= promotedPawns; extraQ++) {
                for (int extraR = 0; extraR + extraQ <= promotedPawns; extraR++) {
                    for (int extraN = 0; extraN + extraR + extraQ <= promotedPawns; extraN++) {
                        int extraB = promotedPawns - extraN - extraR - extraQ;
                        int unpromotedPawns = 8 - promotedPawns;

                        // Promoted pawns should only count towards their new type if the existing ones are alive.
                        // Otherwise we double-count some cases.
                        int minQ, maxQ, minR, maxR, minN, maxN, minB, maxB;
                        if (extraQ == 0) {minQ = 0; maxQ = 1;} else {minQ = maxQ = 1 + extraQ;}
                        if (extraR == 0) {minR = 0; maxR = 2;} else {minR = maxR = 2 + extraR;}
                        if (extraN == 0) {minN = 0; maxN = 2;} else {minN = maxN = 2 + extraN;}
                        if (extraB == 0) {minB = 0; maxB = 2;} else {minB = maxB = 2 + extraB;}

                        for (int numQ = minQ; numQ <= maxQ; numQ++) {
                            for (int numR = minR; numR <= maxR; numR++) {
                                for (int numN = minN; numN <= maxN; numN++) {
                                    for (int numB = minB; numB <= maxB; numB++) {
                                        for (int numP = 0; numP <= unpromotedPawns; numP++) {
                                            // The number of possibilities at these values is (numK + numQ + numR + numN + numB + numP)! / (numK! numQ! numR! numN! numB! numP!)
                                            numCases.get(1+numQ+numR+numN+numB+numP).put(numQ+","+numR+","+numN+","+numB+","+numP, f[1 + numQ + numR + numN + numB + numP] / f[numQ] / f[numR] / f[numN] / f[numB] / f[numP]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            for (int numMen = 1; numMen < 17; numMen++) {
                distribs[promotedPawns][numMen] = numCases.get(numMen).size();
                if (distribs[promotedPawns][numMen] > 0) {
                    for (Long l : numCases.get(numMen).values()) perms[promotedPawns][numMen] += l;
                }
            }
        }

        System.out.println("Num of permutations (cumulative):");
        System.out.println("    max promotions: 0              1              2              3              4              5              6              7              8");
        for (int numMen = 1; numMen < 17; numMen++) {
            System.out.print(String.format("%2d men", numMen));
            long cumul = 0;
            for (int promotedPawns = 0; promotedPawns < 9; promotedPawns++) {
                cumul += perms[promotedPawns][numMen];
                System.out.print(String.format("%15d", cumul));
            }
            System.out.println();
        }

        System.out.println("Entropy of permutations:");
        System.out.println("    max promotions: 0              1              2              3              4              5              6              7              8");
        for (int numMen = 1; numMen < 17; numMen++) {
            System.out.print(String.format("%2d men", numMen));
            long cumul = 0;
            for (int promotedPawns = 0; promotedPawns < 9; promotedPawns++) {
                cumul += perms[promotedPawns][numMen];
                System.out.print(String.format("  %6.3f", Math.log(cumul) / Math.log(2)));
            }
            System.out.println();
        }

    }
}

Como você deduz as posições dos reis? Você usa 15 homens em seu cálculo e nenhum bit especial para posições de rei.
Alin Stoian

@AlinStoian, oops. Eu tive um <pouco do que <=no loop de saída do meu programa. Obrigado por apontar isso. Eu ainda conseguia recuperar a pontuação anterior colocando os 32 homens no quadro, mas não farei isso agora.
Peter Taylor

Dados interessantes! Pior caso teórico com 3 homens capturados #
Level River St

@ steveverrill, o que eu realmente gostaria de fazer é codificar as posições dos peões e o número de promoções em um "bloco" e, em seguida, as posições e valores da peça. No entanto, existem pelo menos 2 ^ 38 posições de peão sem levar em conta as promoções, e enumerá-las eficientemente até agora me escapou.
Peter Taylor

@petertaylor Se você tem apenas 16 peões no tabuleiro, restrito a 48 quadrados, você tem 48! / 32! / 8! / 8! = 29019905518636890 possibilidades. Um pouco mais de 2 ^ 54! Destes, alguns são ilegais, você não pode ter todos os peões de uma cor em um lado do tabuleiro.
Level River St

5

178 bits (174 em uma pitada!) Pior caso

Olá, acabei de voltar à codificação, o que realmente não faço desde a faculdade. Vi este site e achei interessante. Fiz uma pequena verificação terórica e parece que são necessários pelo menos 146 bits para um algoritmo perfeito, provavelmente muito mais (explicarei nos comentários quando tiver um momento).

Enfim, é assim que eu estruturo os dados. O conceito básico é de 178 bits, mas com alguns truques de jiggery, ele pode ser reduzido para 174 (são 21 3/4 bytes). 175 é um pouco mais fácil de programar, mais legível por humanos e ainda dentro de 22 bytes.

A) Posição de ambos os reis: 6 bits cada para brancas e pretas de 12 bits

B) Dos 62 quadrados restantes, quais são ocupados? Uma matriz de 62 bits

C) De quem é a vez? 1 BIT

TOTAL ATÉ: 75 BITS

D) En Passant. Se for a vez das brancas se moverem, até 5 peões pretos podem parecer capturados En Passant. O peão preto deve estar na linha 5 (de baixo para cima começando em zero) e ter um peão branco ao lado. Uma situação com o número máximo de capturas possíveis é assim:

BWBBWBBW

Se houvesse 6 peões pretos na linha 5, o branco teria apenas 2 quadrados para permanecer e só poderia ameaçar 4 peões pretos, portanto, não é possível ter mais de 5 peões pretos aparentemente ameaçados por En passant ao mesmo tempo. Portanto, precisamos de um número de 1 a 5 indicando qual dos (até 5) peões na linha 5 que possui um peão hostil (neste caso branco) próximo a ele foi avançado 2 quadrados no último turno ( ou zero se nenhum peão nessa situação foi movida dessa maneira no último turno.)

E) Dos até 30 quadrados ocupados (sem incluir reis), o que eles contêm?

Existem 10 possibilidades, cada uma representada por um número decimal.

O bit menos significativo representa a cor.

Portanto, números pares são brancos, números ímpares são pretos.

Branco preto

Peão 0/1 (ou Torre com permissão de castelo *)

Knight 2/3

Bispo 4/5

Torre 6/7

Rainha 8/9

* Uma torre com permissão de castelo (e, portanto, nunca foi movida da primeira ou da última linha) é representada por 0 ou 1 em vez de 6 ou 7. Não pode ser confundida com um peão, porque os peões não podem ser encontrados na primeira ou última linha.

Isso fornece um número decimal de até 30 dígitos, que podemos multiplicar por 6 e, em seguida, adicionar o código para En passant. O número resultante caberá em 103 bits, que quando adicionados aos 75 mencionados acima são 103 + 75 = 178 bits . Na verdade, se simplesmente multiplicarmos por 10 em vez de 6, não faz diferença para o número de bits usados ​​e a decodificação é mais fácil.

Isso é apenas 2 bits a mais que 22 bytes. No entanto, podemos reduzi-lo para 174 bits, conforme explicado abaixo.

Se nenhuma peça foi capturada, é impossível promover um peão .

A prova é a seguinte. Imagine que o branco está obcecado em promover seu peão (por exemplo) na coluna E, desde o início do jogo. Há um peão preto em frente a esse peão que está no caminho. Portanto, para promover esse peão, uma das seguintes ações deve acontecer:

1) O peão preto é capturado.

2) O peão preto captura outra peça e, portanto, se afasta do caminho.

3) o peão branco captura um peão em uma coluna adjacente, como a coluna D.

4) o peão branco passa (ou é passado por) um peão preto em uma coluna adjacente e depois captura uma peça nessa mesma coluna adjacente, fazendo com que o peão branco mude de coluna.

O caso 4 é o mais interessante, porque não é apenas o peão branco que começou na coluna E que agora tem um caminho claro para a promoção. O peão preto na coluna que permanece na coluna E também pode ser promovido. Portanto, uma única captura pode abrir caminho para um peão de cada cor promover.

De qualquer forma, o fato de que nenhum peão pode promover até que uma peça seja capturada significa que não precisamos armazenar a 30ª peça. Podemos resolvê-lo por eliminação (ou por subtração, porque o conjunto completo de códigos de peças no início do jogo sempre soma a mesma quantidade = 80). Um ponto menor é que devemos garantir que os quadrados onde as torres A posição no início do jogo está entre as primeiras verificadas (porque, se elas fossem a última, não saberíamos se a torre poderia ter ou não castelo). Isso é facilmente feito pela verificação da linha 0 e das linhas 7 a 1: Para r = 8 a 1 linha de varredura [r mod 8].

Portanto, a matriz de bits em (B) nos dirá quantas peças existem (excluindo reis.) Se houver 30, ignore a última peça ao codificar, o decodificador descobrirá o que era. Agora temos um número decimal de até 29 dígitos, que multiplicamos por 6 e adicionamos ao código En Passant. O número resultante será compactado em 99 bits, resultando em um total de 99 + 75 = 174 bits.

Como exemplo Aqui está uma posição real. As brancas acabam de fazer seu primeiro movimento (peão avançado do rei) e é a vez das pretas.

rnbqkbnr
pppppppp


    P

PPPP PPP
RNBQKBNR

A) Posição dos reis (branco / preto no octal, 12 bits ): 03 73 = 000011 111011

B) Quais quadrados estão ocupados? Comece com a linha zero (linha inferior) e depois todas as outras linhas de cima para baixo, pulando os reis:

1111 111

1111 111
11111111
00000000
00000000
00001000
00000000
11110111 

C) Turno do preto: Turn Bit = 1

D) En Passant. Não existe um peão branco ao lado de um peão preto; portanto, não há peões que possam ser capturados passant (mesmo que esse peão tenha avançado no último movimento), então D = 0. Se, em vez de considerar apenas peões com um peão hostil ao lado, considerarmos todos os peões que não têm peças amigáveis ​​ao lado dos dois lados, D seria 1, pois existe um peão nessa situação, e esse particular o peão foi realmente movido no último turno.

E) Novamente, fileira de baixo primeiro, depois todas as outras fileiras de cima para baixo, pulando os reis e com as quatro torres sem cascas referidas como 0 ou 1 (números normalmente reservados para peões).

RNBQ BNR =   0248 420
rnbq bnr =   1359 531
pppppppp =   11111111
PPPPPPPP = (0)0000000

O trigésimo dígito (entre colchetes) pode ser descartado.

Embora não seja muito aparente aqui, o peão que as Brancas avançaram está na verdade em uma extremidade da lista de peões, porque examinamos linha por linha.

Nossos dados agora são assim, com 29 códigos para o conteúdo dos quadrados, mais o código En Passant:

 (0 discarded) 0000000 11111111 1359531 0248420 (0 en passant)

É melhor digitalizar da direita para a esquerda ao decodificar e da esquerda para a direita (ordem inversa) ao codificar. Isso significa que, quando houver menos peças, teremos um número menor, mantendo a máxima consistência (ou seja, queremos que o espaço em branco / zeros esteja à frente, não à direita, para permitir a compactação de tábuas escassamente ocupadas.) Quando temos apenas dois reis no quadro, teremos os 75 bits mencionados acima, mais 3 bits para armazenar dados passantes = 78 bits no melhor caso. Cada peça adicional vem um pouco abaixo de 3,5 bits (duas peças podem ser armazenadas em 7 bits, porque 100 <128).

Há um problema prático em que um número inteiro de 99 bits é grande demais para caber em uma variável inteira de 64 bits, o que significa que muitas linguagens de programação não fornecem suporte para ele (você não pode simplesmente converter uma representação de string de 29 a 30 dígitos número para um número inteiro.) Como uma maneira fácil de codificar para 22 bytes, que pode quebrar uma série de 30 dígitos (29 códigos peça + de passagem código) em duas 15 algarismos cada uma das quais vai encaixar em 50 bits cada (total de 100 bits além dos 75 mencionados acima, é o pior caso para 175 bits.)

Para a compactação máxima, como mencionado acima, 29 dígitos decimais mais o código En Passant (6 valores possíveis) caberão praticamente em 99 bits (para um total de 174 bits), mas sem o suporte do idioma para números inteiros desse tamanho, é complicado de programar. Pode ser mais fácil separar os 29 bits de cor e trabalhar com os códigos de peça (5 possibilidades) e o código En passant (6 possibilidades) separadamente das cores (70 bits, quase se encaixa em uma variável de 64 bits).


Bom truque com o último homem.
Peter Taylor

5

Aqui está uma solução completa, o pior caso real, 181 bits

O foco aqui é um programa simples que você pode entender facilmente

A entrada é FEN, aqui está a posição de abertura, possui seis campos (5 e 6 ignorados):

rnbqkbnr / pppppppp / 8/8/8/8 / PPPPPPPP / RNBQKBNR w KQkq - 0 1

O primeiro campo (posicionamento da peça) é analisado

perl -pe 's/\d/"_"x$&/ge;s/\s.*//;s|/||g'

Para produzir:

rnbqkbnrpppppppp________________________________PPPPPPPPRNBQKBNR

Campo um: codifique a localização dos reis (12 bits):

printf("%b",index('k',$_))
printf("%b",index('K',$_))

Campo dois: codificar peças (até 5 bits por peça):

s/_/0/g     Blank
s/P/100/g   From here, as normal chess meaning
s/p/101/g
s/Q/11000/g
s/q/11001/g
s/R/11010/g
s/r/11011/g
s/B/11100/g
s/b/11101/g
s/N/11110/g
s/n/11111/g
s/K//
s/k//

Campo três: cor ativa (1 bit)

s/w/0/
s/b/1/

Campo quatro: disponibilidade de rolagem (4 bits)

m/K/?1:0
m/k/?1:0
m/Q/?1:0
m/q/?1:0

Campo cinco: en passant (zero ou 3 bits)

printf("%b",ord($1)-ord("a")) unless m/-/
// The EP's rank is 3 or 6 based on active color, only need to encode file

Pior caso ingênuo 200 bits

  • Colocação de dois reis - 12 bits
  • Borda
    • QRRBBNN QQQQQQQQ - 75 bits
    • qrrbbnn qqqqqqqq - 75 bits
    • Quadrados vazios - 30 bits
  • Cor ativa - 1 bit
  • Castling - 4 bits
  • Em Passante - 3 bits

Pior caso real

Cada jogador não pode promover todos os peões sem capturar outras peças . Aqui está o efeito de entropia da captura de peças:

  • PpR(3 + 3 + 5 = 11 bits) => Qq_(5 + 5 + 1 = 11 bits)
  • PPpp(3 + 3 + 3 + 3 = 12 bits) => QQq_(5 + 5 + 5 + 1 = 16 bits)

Na verdade, o pior caso é:

  • QRRBBNN QQQQQQQQ - 75 bits
  • qrrbbnn qqqq - 55 bits
  • Quadrados vazios - 34 bits

O pior caso é promover todas as peças, em vez de deixar o peão para en passant.

Pior caso real total com código mostrado 12 + 75 + 55 + 34 + 1 + 4 = 181 bits

O FIQ mostra duas melhorias nesse esquema simples, mas são mais difíceis de codificar:

  • Remova o bit 2 da codificação da peça nas linhas 1 e 8, pois os peões não podem ir para lá (economia de até 16 bits)
  • Use peões para codificar torres de concreto (economia de 4 bits)

O único código restante não mostrado nesta resposta (por questões de brevidade) é: quebra da entrada FEN nos campos ( split /\s/) e atribuição de variáveis.


Um jogador pode promover todos os seus peões (dado que ele é capaz de capturar peões inimigos); Qn4QQ / Qb6 / Qq1k4 / Qr6 / Qb6 / Qr6 / Qn4NK / RNB2B1R b - - 0 84
Krzysztof Szewczyk

@KrzysztofSzewczyk, sim, isso é observado acima em PPpp=>QQq_
William Entriken

4

Dados totais precisam de 33 bytes

(Graças a alguém nos comentários, percebi que isso não funciona na promoção de peões. Atualizarei isso quando eu puder resolvê-lo)

para o primeiro byte, usamos cinco bits:

  • primeiro bit: turno do jogador, 1 = branco
  • segundo bit: castelo preto do lado do rei, 1 = castelo
  • terceiro pedaço: castelo lateral da rainha negra, 1 = castelo
  • quarto bit: castelo branco do lado do rei, 1 = castelo
  • quinto bit: castelo lateral da rainha branca, 1 = castelo

os próximos 32 bytes são usados ​​para representar cada peça de xadrez, em uma ordem predefinida

  • 3 bits: representa a linha
  • 3 bits: representa a coluna
  • 1 bit: representa en-passant, 1 = pode en-passant
  • 1 bit: se o bit "can en-passant" for 1: indica de que lado, 0 =
    mais à esquerda representa se foi capturado. 0 = não capturado
    (se pode passar, então definitivamente não é capturado)

Algum código C para representar essa ideia (que na verdade não funciona)

int main() {
    char b, c[32], i;

    //decode:

    FILE *p=fopen("/path/to/file.csv","r");
    fscanf(p,"%d,",&b);
    for(i=0;i<31;i++) fscanf(p,"%d,",&c[i]);
    fscanf(p,"%d",&c[31]);
    fclose(p);
    if(b&16) /* white's turn */
    else /* black's turn */
    if(b&8) /* black king side can castle */
    if(b&4) /* black queen side can castle */
    if(b&2) /* white king side can castle */
    if(b&1) /* white queen side can castle */

    for(i=0;i<32;i++) {
        int row, column;
        row=c[i]&7;
        column=c[i]&56;
        if(c[i]&64 && isPawn(c[i])) { //can en-passant
            if(c[i]&128) //can en-passant to the right
            else //can en-passant to the left
        }
        if(!(c[i]&64)) {
            if(c[i]&128) //captured
            else //not captured
        }
    }

    //encode:

    p=fopen("/path/to/file.csv","w");

    if(b&16) b&=239;
    else b|=16;
    if(black_king_side_cannot_castle) b&=247;
    if(black_queen_side_cannot_castle) b&=251;
    if(white_king_side_cannot_castle) b&=253;
    if(white_queen_side_cannot_castle) b&=254;

    for(i=0;i<32;i++) {
        c[i]=row;
        c[i]+=column*8;
        if(isPawn(c[i]) && can_en_Passant) {
            c[i]|=64;
            if(can_en_Passant_left) c[i]&=127;
            else c[i]|=128;
        }
        if(!(c[i]&64)) {
            if(isCaptured(c[i])) c[i]|=128;
            else c[i]&=127;
        }
    }
    fprintf(p,"%d,",b);
    for(i=0;i<31;i++) fprintf(p,"%d,",c[i]);
    fprintf(p,"%d",c[31]);
    fclose(p);
    return 0;
}

-1, isso não é uma resposta ...
Doorknob

1
Sua ordem predefinida não será muito útil quando um peão atingir a oitava posição e for promovido a cavaleiro, bispo, torre ou rainha.
Ossifrage melindroso

@ Doorknob of Snow ok Estou trabalhando no algoritmo, é um pouco tarde da noite e estou cansado, então estou fazendo isso um pouco mais devagar
pastebin.com slash 0mr8spkT

Bem, por que você postou isso se você nem sequer tem uma solução?
Maçaneta

3
se você ainda acha que essa resposta é ruim e não tem valor aqui, vá em frente e vote para excluí-la e fazer voto negativo e você também pode excluir minha conta aqui. Eu só quero compartilhar o que eu poderia pensar, por que vocês têm que ser tão maus?
usar o seguinte comando

4

256 242 bits

Aqui está um algoritmo básico de compactação que provavelmente pode ser aprimorado porque não exclui a representação de certas posições ilegais.

O quadro começa com 5 bits de informações do cabeçalho, da seguinte maneira:

0 1 1 1 1
---------
1 2 3 4 5

1: Turn (black = 1, white = 0)
2: Black can castle queen-side
3: Black can castle king-side
4: White can castle queen-side
5: White can castle king-side

Então, uma sequência de 12 bits representando as posições dos reis.

0 0 0 1 0 0 1 1 1 1 0 0
-----------------------
0 0 0 0 0 0 0 0 0 1 1 1
1 2 3 4 5 6 7 8 9 0 1 2

01 - 03: white king's rank
04 - 06: white king's file
07 - 09: white king's rank
10 - 12: white king's file

Em seguida, um número enorme de 64 dígitos na base 11, que é multiplicado por 9 para adicionar outro dígito no final representando o estado do en-passant. Cada dígito na base 11 representa um quadrado no quadro, com os seguintes valores possíveis:

0: empty

1: white pawn
2: white knight
3: white bishop
4: white rook
5: white queen

For the black equivalent of each white piece, add 5.

E os dígitos na base 9:

0: no en-passant possible
1 - 8: en-passant on rank 1 - 8

11 64 × 9 é de cerca de 2 224,57 , o que requer 225 bits para codificar. Além disso, os 17 bits de cabeçalho na parte superior representam um total de 242 bits.


Obrigado a ugoren pelas melhorias.


Isso é muito semelhante ao algoritmo do ás, mas usa posições do tabuleiro em vez de peças em uma ordem predeterminada, o que exclui o problema de promoção de peões e permite que os dados sejam cortados um pouco.
Joe Z.

Você pode salvar en-passant como um número entre 0 e 8 (em qual coluna o jogador atual pode capturar en-passant?). 13^64 * 9é 239,99, economizando 11 bits. Economize mais codificando posições king separadamente.
ugoren

De acordo com a maçaneta da Snow, que comentou no meu post, esse tipo de resposta "não é uma resposta". Apenas dizendo. Para sua informação, seu comentário foi publicado antes de eu adicionar o código C à minha resposta.
usar o seguinte comando

@ugoren: eu esqueci disso. Você está certo, esqueci que apenas um peão pode ser passante ao mesmo tempo.
Joe Z.

@ace: sua resposta não é inválida porque não inclui código de codificação e decodificação; é inválido porque não é responsável pelo caso de promoção de peões (nesse caso, sua ordem predefinida de peças não faz nada). O problema, em sua essência, pede um esquema de codificação de dados. O programa é apenas algo para interagir com isso.
Joe Z.

3

? bits

(≥ 217 pior caso, 17 melhor caso, 179 para o quadro inicial)


Descrição da codificação

Metadados extras consistem em quem é a vez (um bit) e roque (quatro bits, ou seja, pode o castelo branco do lado dos reis - do lado das rainhas - e da mesma forma para o preto).

Para a própria posição do tabuleiro, nós o codificamos como um conjunto de peças ativas. Bem, na verdade, certifique-se de enumerar as peças em uma ordem específica por razões que explicarei um pouco. Para cada peça, armazenamos sua cor (um bit), seu tipo (três bits para abranger 6 tipos, mais um tipo extra para "peão ​​que pode ser levado por en passant"), bem como sua posição.

Aqui está a parte interessante: para codificar a posição de uma peça, em vez de armazená-la como coordenada, armazenamos sua distância relativa da última peça ao enumerar as peças na ordem da esquerda para a direita e de cima para baixo (por exemplo, A8 , B8, ..., G1, H1). Além disso, armazenamos a distância como um número de comprimento variável, usando 1para significar que esta peça está ao lado da anterior, 0xxpara pular 1-3 peças, 000xxxpara pular 4-10 peças, 000000xxxxpara 11-25, 0000000000xxxxxpara 26-56 e finalmente 000000000000000xxxpara 57-62.

Exemplos

Fiz um resumo de algumas posições codificadas com essa codificação e anotei a posição inicial com alguns comentários.

Não sei como analisar o pior tamanho de bit, mas seguindo os exemplos da essência, acredito que o algoritmo deve ser um pouco eficiente, pelo menos.


Implementação do decodificador

Abaixo está um decodificador rápido e sujo para essa codificação (tomando como entrada os dados binários codificados no texto, como no exemplo anotado acima, e pulando sobre coisas que não são '0' ou '1'). Produz um tabuleiro de xadrez unicode para stdout.

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

char buf[1024];
int wi = 0, ri = 0;

int read_n(int n) {
  int res = 0;
  for (int i = 0; i < n; i++) {
    res = res << 1 | (buf[ri++] == '1');
  }
  return res;
}

int read_varnum() {
  int v, c = 0;

  for (int i = 1; i <= 5; i++) {
    v = read_n(i);
    if (v != 0) return c + v;
    c += (1 << i) - 1;
  }

  assert(false); /* Shouldn't happen */
}

char *piece_to_str(int piece, int color) {       /* ↓ pawn that may be taken with en passant */
  char *pieces[] = { "♙", "♘", "♗", "♖", "♕", "♔", "♙",
                     "♟", "♞", "♝", "♜", "♛", "♚", "♟" };
  return pieces[color * 7 + piece];
}

int main(void) {
  int ch;
  while (ch = getchar(), ch != EOF) {
    if (ch == '0' || ch == '1') buf[wi++] = ch;
  }

  int board[64];
  memset(board, -1, 64 * sizeof(int));

  /* Read metadata */
  int is_white = read_n(1);
  int castling = read_n(4);

  /* Read the board state */
  int bi = -1;
  while (ri != wi) {
    int color = read_n(1);
    int kind  = read_n(3);
    int delta = read_varnum();
    board[bi + delta] = color << 8 | kind;
    bi += delta;
  }

  /* Print metadata */
  printf("  Current turn: %s's turn to play.\n", is_white? "white" : "black");
  printf("  Castling: White may castle? %s %s\n",
         castling & 0x8? "left" : "", castling & 0x4? "right" : "");
  printf("            Black may castle? %s %s\n",
         castling & 0x2? "left" : "", castling & 0x1? "right" : "");
  printf("\n");

  /* Print the board out */
  printf("+");
  for (int x = 0; x < 8; x++) printf("--");
  printf("-+\n");

  for (int y = 0; y < 8; y++) {
    printf("|");
    for (int x = 0; x < 8; x++) {
      int piece = board[y*8 + x],
          color = piece >> 8,
          kind  = piece & 0xFF;

      if (piece == -1) printf("  ");
      else printf(" %s", piece_to_str(kind, color));
    }
    printf(" |\n");
  }

  printf("+");
  for (int x = 0; x < 8; x++) printf("--");
  printf("-+\n");

  return 0;
}

Não faço ideia do que é o seu pior número de bits, mas suspeito que seja consideravelmente mais do que 179 bits. Por exemplo, como seu algoritmo lidaria com esse layout ? (A propósito, é válido; fiz isso usando o editor em chess.com )
ossifrage escrúpulos

@squeamishossifrage que parece exigir 217 bits: gist.github.com/FireyFly/8639791 (obrigado pelo caso de teste, eu queria experimentá-lo com um mais complicado!)
FireFly

Ei, isso não é ruim. Continue!
Ossifrage melindroso

2

Máx: 184 bits, Mín: 75 bits

Fui inspirado pela Huffman da @ AdamSpeight que codifica peças para tentar criar meu próprio esquema. Duvido que isso vença, mas tem limites calculáveis.

Este esquema trata as peças de xadrez como se houvesse 11 tipos diferentes de peças. Segui aproximadamente o algoritmo de codificação Huffman para agrupar essas classes por suas frequências e tipos reais para gerar as seguintes codificações:

 Piece Class                | Frequency Per Team | Encoding
============================+====================+==========
 Pawn, normal               | 0 - 8              | 0
 Pawn, jumped two last turn | 0 - 1              | 1111
 Knight                     | 0 - 2              | 1000
 Bishop                     | 0 - 2              | 1001
 Queen-side rook, unmoved   | 0 - 1              | 10100
 Queen-side rook, moved     | 0 - 1              | 10101
 King-side rook, unmoved    | 0 - 1              | 10110
 King-side rook, moved      | 0 - 1              | 10111
 Queen                      | 0 - 1              | 1110
 King, unmoved              | 0 - 1              | 1100
 King, moved                | 0 - 1              | 1101

O código de cada peça pode ser precedido por dois bits para mostrar a qual time pertence ( 10para branco, 11para preto). 0pode ser usado para codificar espaços vazios. Essas idéias nos permitem criar uma codificação quadrado por quadrado para todo o quadro, usando o procedimento que desejarmos. Assumirei a ordem da iteração a1, b1, c1, ... f8, g8, h8. Isso significa que apenas listar esses códigos, como mostrado acima, codifica todas as informações, exceto de quem é a vez. Um mecanismo de xadrez muito simples pode usar as "classes" para peões, torres e reis para determinar se o castiçal e o passante são legais. Além disso, esse esquema lida facilmente com promoções de peões. Se um jogador promove um peão para uma torre, os códigos do rei ou da rainha podem ser usados ​​desde que a variante "movida" seja escolhida.

Exceto as posições patológicas que eu acho que nunca aconteceriam, o pior cenário para essa codificação é quando todas as peças ainda estão no tabuleiro e o jogador anterior moveu um peão para a frente dois espaços. Como exemplo, o quadro abaixo codifica 1. e4:

1101010010100010100110111010110010100110100010101101001001001100100100100000000000000101111000000000000000000011011011011011011011011011101001110001110011111101111001110011110001110110
===========================================================================
                              Black's move
1110100 111000 111001 111110 111100 111001 111000 1110110 | r n b q k b n r
    110    110    110    110    110    110    110     110 | p p p p p p p p
      0      0      0      0      0      0      0       0 | . . . . . . . .
      0      0      0      0      0      0      0       0 | . . . . . . . .
      0      0      0      0 101111      0      0       0 | . . . . P . . .
      0      0      0      0      0      0      0       0 | . . . . . . . .
    100    100    100    110      0    100    100     100 | P P P P . P P P
1010100 101000 101001 101110 101100 101001 101000 1010110 | R N B Q K B N R

Isso significa que a pior codificação tem 184 bits: 1 para indicar o jogador, 32 para os espaços vazios, 45 para os peões imóveis, 6 para o peão com dois saltos, 24 para os cavaleiros, 24 para os bispos, 28 para as torres, 12 para as rainhas e 12 para os reis.

À medida que as peças se movem e são capturadas, o tamanho da codificação diminui. O melhor cenário é representado por dois reis sozinhos no tabuleiro: 1 bit para indicar o jogador + 62 bits para indicar os quadrados vazios + 12 bits para indicar os reis fornece um comprimento mínimo de 75 bits.

Voltarei e editarei esta resposta com algum código que demonstra essa codificação em ação mais tarde hoje ou amanhã. Por enquanto, estou curioso para ver o que as outras pessoas pensam dessa codificação.


1
Você pode salvar bits nas torres. Você pode determinar o lado da rainha e o rei com base na posição, e não precisa saber de que lado veio a torre movida. então você só precisa de um pouco de informação sobre a torre - movida ou imóvel.
Não que Charles,

... E, na verdade, armazenar esses dados em um nível de peça é mais fácil de codificar / decodificar, mas se você acabou de armazenar um marcador no início, poderá salvar os bits na pior das hipóteses (por exemplo, o marcador 11001significa B'S MOVE W CAN KSC W CANT QSC B CANT KSC B CAN QSC). Ou seja, 4 bits em vez dos 5 bits por lado na sua codificação ou 3 bits por lado se você eliminar o marcador lateral nas torres. ( KSCCastelo = Rei-lado. QSC= Castelo Queen's-side)
Não que Charles

Além disso, devido a promoções, é perfeitamente possível ter até 9 rainhas ou 10 cavaleiros (ou qualquer outro não-régia, peça não-peão)
Não que Charles

1

184 bits = 23 bytes no pior caso, e não é muito complicado:

A. Quais quadrados ocupados: 64 bits = 8 bytes B. Quais cores para os <= 32 quadrados ocupados: 32 bits = 4 bytes E agora usando apenas os <= 30 quadrados ocupados por não-reis: B. use o PNBRQ codificado em raiz 5, para 5 ^ 30 possibilidades; e 32 * 31 * 2 * 4 * 4 * 9 para posições de rei, direitos de cor castanho, branco e preto, en passant square (entre 8 possibilidades mais nenhuma, a 9); esse número 5 ^ 30 * 32 * 31 * 2 * 4 * 4 * 9 = 266075134277343750000000000 = 2 ^ 87.782 se encaixa em 88 bits para um total de 64 + 32 + 88 = 184 bits para toda a codificação.

Isso pode ser reduzido, por exemplo, 32 * 31 * 2 * 4 * 4 * 9 = 285696 pode ser reduzido para 2 * (32 * 31 + 31 * 3 + 31 * 3 + 3 * 3) * 6 = 14244, usando fact no máximo 6 en vítimas-candidatos passantes (incluindo nenhuma) e codificação de direitos de castling e posições de rei dentro do mesmo conjunto usando direitos de castling de fatos apenas importam quando rei no quadrado inicial. Isso economiza 4 bits.

Tenho motivos para acreditar que não é possível obter 18 bytes, ou seja, o número total de posições legais no xadrez excede 2 ^ 144.

Seu esquema de 160 bits é muito engenhoso, mas acho que ele precisa ser fornecido como programas de codificação / decodificação antes de estar completamente confiante.


1

Pior caso de 171 bits:

Combinei algumas idéias e alguns de meus próprios pensamentos.

Vamos começar com uma placa de 64 bits. Cada bit representa um espaço ocupado no quadro. Eles preenchem ao longo das linhas. Portanto, o início se parece com:1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111

Agora, cada peça será representada por 4 bits. 1º bit: color ( 0=white, 1=black) 2º-4º bits: um dos 8 tipos.

0=king, 1=queen, 2=bishop0, 3=knight, 4=rook, 5=pawn0, 6=pawn1, 7=bishop1

No final, incluiremos um pouco para designar a curva. 0=white, 1=black.

4bits * 32 peças = 128 bits e já tenho 64 + 1 no turn e no board. Isso dá um total de 128 + 64 + 1 = 193 que eu nem comecei com en passant ou castling. Bem acima do meu limite sem nada - nem sequer vira. É aqui que os truques começam.

Ok - você vê esses tipos acima? Bishop0 e Bishop1? Peão0 e peão1? Esses tipos são assim designados, porque nos dizem um pouco para inserir depois desta peça. Portanto, Bishop0 significa que, depois disso, haverá um 0 - ou seja, a próxima peça será branca. Bishop1 nos diz que a próxima peça é preta, e o peão0 e o peão1 funcionam da mesma maneira. (Se esta peça é a última peça sendo enumerada, ela nos informa sobre o próximo turno).

Meu pior caso envolve todas as peças do tabuleiro; portanto, com 16 peões e 4 bispos, isso me economiza 20 bits. Estou com 173.

OK. Por outro lado, no meu pior caso - uma vez que há 16 cores codificadas, paramos de codificar cores - como a conhecemos. Meu pior caso agora envolve uma peça branca chegando ao canto mais distante sem capturas. Lá, economizo apenas um pouco. 172

Agora vou mudar a ordem em que nomeio as peças. Vamos nomeá-los ao longo de colunas começando do lado de fora, movendo-se para dentro. O quadro nomeado no início permanecerá o mesmo, mas quando eu coloco peças nele, começo de branco no canto inferior direito e subo a coluna. Então pulo para o canto inferior direito do preto e subo a coluna. Eu pulo para a célula desconhecida no canto inferior direito do branco, e assim por diante - isso significa que meu pior caso é novamente o começo. Minha razão tem a ver com o meu truque passante, os próximos dois bits que eu perco e com a bola.

Agora, para que um peão seja promovido (como já foi discutido em detalhes), uma peça deve ser capturada. Assim, quando sabemos que existem 32 peças, precisamos apenas denotar 31 delas. A última peça é identificada exclusivamente. Acontece que, para mim, isso economiza apenas 2 bits - porque minha última peça pode ser um peão / bispo (que normalmente me custa 3 bits porque eu salvo uma na peça seguinte), cuja cor já está determinada e, portanto, era apenas 2 bits. Estou com 170 bits.

Quando os peões são promovidos, eles simplesmente mudam de tipo. Para cada peça que sai do tabuleiro, me livrei de (no mínimo) 3 bits e duas promoções de peão me custaram 2 bits, então estou recusando (lentamente) as promoções.

Castling. Para que o roque aconteça, nem rei nem torre relevante podem ter se movido. Assim, quando uma torre é capaz de arremessar, ela e o rei estarão em seus lugares originais. Assim, as torres capazes de rolar serão listadas no mesmo local que os reis dessa cor. Como isso é ilegal (dois reis ou três da mesma cor no quadro) e só pode acontecer em três configurações possíveis para cada cor (esquerda, direita, ambas as torres são listadas como reis) - a decodificação é totalmente possível. Portanto, para nenhum bit codificamos o castling.

En Passant Aqui também usaremos posições ilegais. Apenas um peão pode estar em risco de passante de cada vez. Ele deve estar na quarta linha. O peão vulnerável será 'invertido' de volta à sua linha inicial - alternado com o que estiver lá. Como esse peão está em sua própria primeira linha - uma posição ilegal, a situação será óbvia para o decodificador - ele reverterá as posições e marcará o peão como vulnerável a passantes.

Precisávamos mexer com o pedido, porque a última peça precisa ser 'identificada exclusivamente'. Em uma ordem padrão, não poderíamos dizer se a torre no canto de trás poderia se erguer - isso não é conhecido. Quando trabalhamos de fora para dentro, garantimos que, onde quer que a torre seja 'listada', seja em seu próprio canto ou no meio do tabuleiro, porque foi trocada por um peão passável e vulnerável, haverá uma peça listada depois - então nos dizem o tipo da torre. Sabemos que haverá uma peça depois dela, porque, para que um peão seja vulnerável, deve haver um peão em seu interior (que será crucialmente codificado posteriormente conforme as instruções acima).

Ah, e para ajudar a garantir que o pior caso envolva todas as peças do tabuleiro, uma vez que tenhamos menos de 32 peças, podemos usar a placa de 64 bits para identificar as curvas e as posições ocupadas usando 0 para representar peças quando as peças brancas virar e 1 quando é preto virar.

Então, nós passamos e passamos de graça. Escolhemos a última peça de graça, embora demorasse algum tempo para finalizar o jogo com as regras do passante e do castling. Abaixamos 20 bits nas peças padrão. Creio que o pior caso aqui envolve um peão branco médio movido para frente e uma peça preta entre ela e sua rainha enquanto todas as peças estão no tabuleiro. Verificação dupla rápida: a primeira peça é capturada - chame-a de peão, 3 bits do tabuleiro no peão, 3 bits no tabuleiro na forma de uma última peça, um bit no marcador de turno desaparecendo. Promova dois peões 2 bits novamente no tabuleiro. Ah, droga, estou com 171.

EDIÇÃO Adicionei código para um decodificador (funcionando?) - no R - abaixo. Pega vetores de booleanos como entrada - (desculpe, eu não sou capaz de codificar bem em qualquer coisa que me permita realmente usar os bits). Também incluí a posição inicial.

separate = function(vec){
    #Using a boolean vector (sorry R doesn't handle bits well and this will build quickest)
    board = matrix(vec[1:64],8,8,byrow=T)
    npieces = min(sum(board),64-sum(board))
    n = length(vec)
    a = vec[65:n]
    counter = 0
    pieces = list()
    white = 0
    Letters=c(letters,LETTERS)
    for (i in 1:npieces){
        col = ifelse(a[1],"black",{white=white+1;"white"})
        typ = a[2:4]
        a=a[-(1:4)]
        num = 4*typ[1] + 2*typ[2] + typ[3]
        type = switch(letters[num+1],a="king",b="queen",c="knight",d="rook",e="bishop0",f="bishop1",g="pawn0",h="pawn1")
        if (num > 3) {
            if(num%%2){
                a = c(T,a)
            } else {
                a = c(F,a)
            }
            type = substr(type,1,nchar(type)-1)
        }
        pieces[[Letters[i]]] = list(color=col,type=type)
        if (length(pieces)==31&&npieces==32) {
            col = ifelse(16-white,{white=white+1;"white"},"black")
            type = "TBD"
            pieces[[Letters[i+1]]] = list(color=col,type=type)
            break
        }
    }

    if (npieces==32) {
        f=function(y){sum(sapply(pieces,function(x)x$type==y))}
        if (f("pawn")<16) {pieces[[32]]$type="pawn"}
        if (f("bishop")<4) {pieces[[32]]$type="bishop"}
        if (f("knight")<4) {pieces[[32]]$type="knight"}
        if (f("queen")<2)  {pieces[[32]]$type="queen"}
        if (f("king")<2)   {pieces[[32]]$type="king"}
        if (f("rook")<(6-f("king"))) {pieces[[32]]$type="rook"}
    }
    return(list(board,pieces,turn=ifelse(a[length(a)],"black","white")))
}


fillboard = function(out) {
    board = out[[1]]
    pieces = out[[2]]
    turn = out[[3]]
    lpieces = lapply(pieces,function(x) paste(substr(x$color,1,1),x$type))
    game = matrix("     ",8,8)
    #Start with corners.
    a = c(1,57,8,64)
    #Then kings
    b = c(25,32)
    #Then rooks in en passant
    c = c(4,60,5,61)
    #Then kings in en passant
    d = 28:29
    exceptions = list(a,b,c,d)
    for (places in exceptions) {
        c= which(board[places])
        if (length(c)) {
            repl = lpieces[1:length(c)]
            game[places[c]] = unlist(repl)
            board[places] = F
            lpieces = lpieces[-(1:length(c))]
        }
    }
    #Loop through rows.
    for (i in c(1:4,8:5)) {
        j = which(board[i,])
        if (length(j)) {
            repl = lpieces[1:length(j)]
            game[i,j] = unlist(repl)
            board[i,j] = F
            lpieces = lpieces[-(1:length(j))]
        }
    }
    return(matrix(unlist(game),8,8,F))
}

swapillegal = function(matr) {
    mat = matr
    if (any(mat[8,]=="b pawn")) {
        j = which(mat[8,]=="b pawn")
        mat[8,j] = mat[5,j]
        mat[5,j] = "b pawn-e"
    }
    if (any(mat[1,]=="w pawn")) {
        j = which(mat[1,]=="w pawn")
        mat[1,j] = mat[4,j]
        mat[4,j] = "w pawn-e"
    }

    if (sum(mat[8,]=="b king") > 1) {
        j = which(mat[8,-4]=="b king")
        j[j==7] = 8
        mat[8,j] = "b rook-c"
    }
    if (sum(mat[1,]=="w king") >1) {
        j = which(mat[1,-4]=="w king")
        j[j==7] = 8
        mat[1,j] = "w rook-c"
    }
    return(mat)
}

decode = function(vec) {
    a = separate(vec)
    b = fillboard(a)
    c = swapillegal(b)
    list(board=c,turn=a[[3]])
}


startboard = c(rep(T,16),rep(F,32),rep(T,16))
#Re-ordering -- first spots will be the corners. Then kings. then en passant positions of those spots
pieces = c(F,F,T,T,F,F,T,T,T,F,T,T,T,F,T,T,F,F,F,F,T,F,F,F,F,F,T,F,F,T,F,F,F,F,T,F,T,F,F,F,T,F,F,T,T,F,T,T,F,T,T,F,T,T,F,T,T,F,T,T,F,T,T,F,T,T,T,F,T,F,T,T,F,T,F,F,T,T,T,F,T,F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,F)
########## w rook -w rook -B rook -B rook -W king -B king -w kni  -w bi 0 -w Q  -w Bi 0 -w kni-w p0   - 2   -   3 -  4  - 5   -  6  -  7  -w p1 -b kni-b bi1  -b q  -b bi1  -b kni-b p1   -2    - 3   - 4   - 5   - 6   - b p0- implicit b p0.
#After the kings come all the prior en passant positions. which are empty at start. Then we start at whites bottom right, and move across rows to middle. Then we go to blacks bottom left, and fill across to the middle.
#Changing start to properly encode rooks for castling
newpieces= c(F,F,F,F,F,F,F,F,T,F,F,F,T,F,F,F ,pieces[-(1:16)])
test2 = decode(c(startboard,newpieces))

Este código cria 4 funções. Um que faz uma separação básica das peças e da estrutura do tabuleiro, além de descobrir o tipo de peça e quaisquer peças "implícitas". A próxima função preenche a estrutura do quadro com essas peças em uma ordem ligeiramente bizarra (e diferente da do meu algoritmo inicial) [explicada nos comentários do código]. A próxima função pega a placa preenchida e detecta todas as posições ilegais - ela as corrige e renomeia os peões que são vulneráveis ​​ao passante "x peão-e" e a qualquer torre que possa "x rook-c". A função final é um invólucro que executa essas funções em ordem e fornece uma saída que é a placa atual e também o turn.

Também incluí a codificação da posição inicial (no entanto, para vê-lo, você precisará chamar c(startboard,newpieces)e o código chama a função wrapper nessa posição.


Isto é interessante. Eu adoraria ver uma implementação de trabalho como uma prova de conceito.
Mego

A implementação geralmente está algumas etapas além da prova de conceito, mas eu adicionei um decodificador. Está em R e, portanto, usa booleanos em vez de bits (desculpe - não queria usar muito tempo). Mas acredito que deve ser uma prova de conceito.
user5957401

0

229/226 bits

Isso não é muito bem-sucedido, mas pode salvar outras pessoas no mesmo caminho.

A versão simples:

  • 1 pouco para quem é a vez
  • 4 bits para as quatro possibilidades de rolagem
  • 3bits para as possibilidades en passant . Isso tem mais profundidade do que eu entendi a princípio. En passant deve ser feito por um peão que se move da mesma fila (linha) que o peão que é capturado. A análise de caso indica que, uma vez que sabemos quantos peões da cor que foi movida pela última vez avançaram exatamente dois quadrados, haverá no máximo 6 casos passantes (incluindo o caso em que não há peão vulnerável a passantes ). O pior caso são 5 peões (potencialmente todos vulneráveis: por exemplo, PpPPpPPptem cinco vulneráveis P). Com 6 peões, existem no máximo 2 peões inimigos na mesma fila, cada um dos quais pode ameaçar no máximo 2 peões de passagem . Portanto, precisamos de ceil(lg 6) = 3bits aqui.

Depois o quadro. A placa possui 64 quadrados, portanto, um índice quadrado pode ser codificado em 6 bits. Listamos os homens por categoria, cores alternadas, começando pelo rei.

  • 6bits: posição do rei branco. (Garantido para estar no quadro).
  • 6bits: posição do rei preto. (Garantido para estar no quadro. No pior dos casos, o rei branco está em um canto, existem 60 lugares possíveis; ele pode estar; no melhor caso, o branco não está no limite, existem 55).
  • 6bits: posição da rainha branca. Se não houver rainha branca, repita a posição do rei branco como sinal.
  • Para cada rainha branca adicional, um 1pouco seguido por 6 bits para a posição.
  • Um 0pouco
  • O mesmo vale para as damas negras.
  • Processo semelhante para gralhas, bispos, cavaleiros e peões, embora possamos pular os peões de uma cor se já tivermos 16 homens dessa cor.
  • Exclua o 0bit final .

Isso custa alguns 12bits para os reis e 2*7*5-1 = 69bits para os outros homens. Na pior das hipóteses, todos os 32 homens estão no conselho, custa 7bits para cada homem que não seja os reis, no total 12 + 7*30 - 1 = 221 bits. Portanto, com os 8bits iniciais do estado global, temos 229 bits .


A versão avançada:

Usando a codificação aritmética, podemos operar com lg num_possibilitiese não usar ceil(lg num_possibilities)apenas uma ceilno final.

  • 1 pouco para quem é a vez
  • 4 bits para as quatro possibilidades de rolagem
  • lg 6bits para as possibilidades en passant .
  • 6 bits para o rei branco
  • lg 60 bits (pior caso) para o rei preto
  • lg 63 bits (porque eu não quero complicar ao nível de verificações) da rainha branca, usando a posição do rei branco se não houver
  • Para cada rainha branco adicional, um 1pouco, seguido por lg 62, lg 61, etc. bits para a sua posição.
  • Um 0pouco
  • lg 63 bits (ou menos, se houver rainhas brancas) para a rainha negra.
  • etc.

O enésimo homem que está realmente presente tem 66-nvalores possíveis. Se um tipo estiver ausente para uma cor, gastamos 66-#men so farbits gravando isso (mais um bit para o separador). Os casos extremos são:

  1. Todos os homens presentes, incluindo pelo menos um peão desprotegido de cada lado. Nós gastamos 5+lg 6no estado global, 6+lg 60nos reis, 29em bits separadores e SUM_{n=32}^{63} lg nbits em posições. Total geral: ceil(225.82)bits. Decepcionante.
  2. Restam apenas peões desprotegidos. Nós gastamos 5+lg 6no estado global, 6+lg 60nos reis, 29nos bits separadores, 8*lg 63dizendo que não há outras peças e SUM_{n=48}^{63} lg nnas posições dos peões. Total geral: ceil(188.94)bits. Melhor - salvando a segunda torre, cavaleiro e bispo para cada lado que avançamos um pouco.

Portanto, o pior caso parece ser 226 bits , para uma economia de 3.

Definitivamente, podemos fazer melhor codificando peões antes de peças, já que eles são restritos a 48 quadrados em vez de 64. No entanto, no pior dos casos, todos os homens estão no tabuleiro e todos os peões foram promovidos, eu acho. isso acabaria custando 2 bits a mais porque precisaríamos de uma bandeira "sem peões" em vez de poder contar os homens.


0

Este é um tópico de discussão nos círculos de xadrez.

Aqui está uma prova muito simples com 164 bits https://groups.google.com/forum/#!topic/rec.games.chess.computer/vmvI0ePH2kI 155 é mostrada aqui http://homepages.cwi.nl/~tromp /chess/chess.html

Sobre estratégia simplificada:

  • Limite os peões para o local onde os peões podem ser encontrados
  • Limite de exércitos para considerar peças originais e possíveis promoções de peões
  • Pense bem em promoções e situações em que promoções não são possíveis

2
Respostas somente de link não são boas. Você deve fornecer a resposta completa em sua postagem, não apenas alguns links para a resposta. E se sua resposta não for seu próprio trabalho, você provavelmente deve tornar seu post um wiki da comunidade.
usar o seguinte comando

A postagem é original. Adicionando detalhes para responder.
William Entriken

1
Este é um exemplo de por que você inclui o conteúdo em sua resposta. O segundo link está morto. É isso? tromp.github.io/chess/chess.html
mbomb007

-2

Mín: 0 bits

Máx: 1734 243 bits (4,335 4,401 bits / placa amortizados)

Esperado: 351 177 bits (4,376 4.430 bits / placa amortizados)

Como eu posso determinar a entrada e a saída, no entanto, eu quero que eu decidi continuar com a codificação do histórico do jogo até este ponto. Uma vantagem é que as informações adicionais sobre quem é a vez, são passivas e quem tem a capacidade de localizar onde podem ser derivadas e não codificadas.

Tentativa 1:

Ingenuamente, pensei que poderia codificar cada movimento em 12 bits, 4 trigêmeos da forma (início x, início y, final x, final y), onde cada um possui 3 bits.

Assumiríamos a posição inicial e moveríamos as peças a partir daí, com o branco indo primeiro. O quadro é organizado de forma que (0, 0) seja o canto inferior esquerdo do branco.

Por exemplo, o jogo:

  e4    e5
 Nf3    f6
Nxe5  fxe5
...    ...

Seria codificado como:

100001 100010 100110 100100
110000 101010 101110 101101
101010 100100 101101 100100
...

Isso leva a uma codificação de 12 m bits em que m é o número de movimentos feitos

Por um lado, isso pode ficar muito grande; por outro, você pode considerar cada jogada como sendo seu próprio jogo, de modo que cada codificação realmente codifique m "tabuleiros de xadrez". Se você amortizou isso, obtém que cada "tabuleiro de xadrez" é de 12 bits. Mas acho que isso é um pouco trapaceiro ...

Tentativa 2:

Percebi que cada movimento na tentativa anterior codifica muitos movimentos ilegais. Então, decidi codificar apenas movimentos legais. Enumeramos os movimentos possíveis da seguinte forma, numere cada quadrado de modo que (0, 0) → 0, (1, 0) → 1, (x, y) → x + 8 y. Itere através dos ladrilhos e verifique se há uma peça e se ela pode se mover. Nesse caso, adicione as posições que podem ser encontradas em uma lista. Escolha o índice da lista que é a jogada que você deseja fazer. Adicione esse número ao total de movimentos em execução, ponderado por 1, mais o número de movimentos possíveis.

Exemplo como acima: A partir da posição inicial, a primeira peça que pode ser movida é o cavaleiro no quadrado 1, pode ser movida para o quadrado 16 ou 18, portanto, adicione-as à lista [(1,16),(1,18)]. Em seguida é o cavaleiro no quadrado 6, adicione seus movimentos. No geral, temos:

[(1,16),(1,18),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(11,19),(11,27),(12,20),(12,28),(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]

Como queremos a jogada (12, 28), a codificamos como 13 na base 20, pois existem 20 jogadas possíveis.

Então agora temos o número do jogo g 0 = 13

Em seguida, fazemos o mesmo para o preto, exceto que numeramos os blocos ao contrário (para facilitar, não é necessário) para obter a lista de movimentos:

[(1,16),(1,18),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(11,19),(11,27),(12,20),(12,28),(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]

Como queremos a jogada (11, 27), a codificamos como 11 na base 20, pois há 20 jogadas possíveis.

Então agora temos o número do jogo g 1 = (11 ⋅ 20) + 13 = 233

A seguir, temos a seguinte lista de movimentos para o branco:

[(1,16),(1,18),(3,12),(3,21),(3,30),(3,39),(4,12),(5,12),(5,19),(5,26),(5,33),(5,40),(6,12),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(11,19),(11,27)(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]

Como queremos a jogada (6, 21), nós a codificamos como 13 na base 29, pois existem 29 possíveis.

Então agora temos o número do jogo g 2 = ((13 ⋅ 20) + 11) 20 + 13 = 5433

A seguir, temos a seguinte lista de movimentos para preto: [(1,11),(1,16),(1,18),(2,11),(2,20),(2,29),(2,38),(2,47),(3,11),(4,11),(4,18),(4,25),(4,32),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(12,20),(12,28),(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]

Como queremos a mudança $ (10, 18) $ (10, 18)

Então agora temos o número do jogo g 3 = (((19 ⋅ 29 + 13) 20) + 11) 20 + 13 = 225833

E continue esse processo para todos os movimentos restantes. Você pode pensar em g como a função g (x, y, z) = x y + z. Assim, g 0 = g (1, 1, 13), g 1 = g (g (1, 1, 11), 20, 13), g 2 = g (g (g (1, 1, 13), 20, 11), 20, 13), g 3 = g (g (g (g (1, 1, 19), 29, 13), 20, 11), 20, 13)

Para decodificar um número de jogo g 0 , começamos na posição inicial e enumeramos todos os movimentos possíveis. Em seguida, calculamos g 1 = g 0 // l , m 0 = g 0 % l , onde l é o número de movimentos possíveis, '//' é o operador de divisão inteira e '%' é o operador de módulo. Deveria sustentar que g 0 = g 1 + m 0 . Em seguida, fazemos o movimento m 0 e repetimos.

A partir do exemplo acima, se g 0 = 225833, em seguida, g 1 = 225833 = 20 // 11291 e m 0 = 225833% 20 = 13. Próximo g 2 = 11291 // 20 = 564 e m 1 = 11291% 20 = 11. Então g 3 = 11291 // 20 = 564 e m 2 = 11291% 20 = 11. Portanto, g 4 = 564 // 29 = 19 e_m_ 3 = 564% 29 = 13. Finalmente g 5 = 19 // 29 = 0 e m 4 = 19% 29 = 19.

Então, quantos bits são usados ​​para codificar um jogo dessa maneira?

Para simplificar, digamos que sempre haja 20 movimentos a cada turno e, no pior dos casos, sempre escolhemos o maior, 19. O número que obteremos é 19 is 20 m

+ 19 ⋅ 20 m-1 + 19 ⋅ 20 m-2 + ⋯ + 19 ⋅ 20 + 19 = 20 m + 1 - 1 onde _m é o número de movimentos. Para codificar 20 m + 1 - 1, precisamos do log 2 (20 m + 1 ) bits que é de cerca de (m + 1) ∗ log 2 (20) = 4,3219 ∗ (m + 1)

Em média, m = 80 (40 movimentos por jogador), o que levaria 351 bits para codificar. Se estivéssemos gravando muitos jogos, precisaríamos de uma codificação universal, pois não sabemos quantos bits cada número precisará

Na pior das hipóteses, quando m = 400 (200 movimentos por jogador), isso levaria 1734 bits para codificar.

Observe que a posição que queremos codificar deve ser dada pelo caminho mais curto para chegar lá, seguindo as regras. Por exemplo, o jogo teorizado aqui não precisa de m = 11741 para codificar a posição final. Em vez disso, executamos uma pesquisa de largura em primeiro lugar para encontrar o caminho mais curto para essa posição e codificá-la. Não sei até que ponto precisaríamos ir para enumerar todas as posições do xadrez, mas suspeito que 400 seja uma superestimação.

Cálculo rápido:

Existem 12 peças únicas ou o quadrado pode estar vazio, portanto, para posicioná-las em um tabuleiro de xadrez é 13 64 . Essa é uma superestimação enorme, pois inclui muitas posições inválidas. Quando estamos m movimentos de jogo, criamos cerca de 20 m posições. Então, estamos procurando quando 20 m = 13 64 . Registre os dois lados para obter m = 64 * log 20 (13) = 54,797. Isso mostra que devemos conseguir chegar a qualquer posição em 55 movimentos.

Agora que calculei o pior caso para m = 55 e não m = 400, editarei meus resultados. Para codificar uma posição em que m = 55 leva 243 bits. Também vou dizer que o caso médio é de cerca de m = 40, o que leva 177 bits para codificar.

Se usarmos o argumento de amortização anterior, codificamos 400 "tabuleiros de xadrez" em 1734 bits, para que cada "tabuleiro de xadrez" ocupe 4,333 bits no pior dos casos.

Observe que g = 0 indica um jogo válido, aquele em que a peça no quadrado mais baixo se move para o quadrado mais baixo possível.

Notas Adicionais:

Se você quiser se referir a uma posição específica no jogo, pode ser necessário codificar o índice. Isso pode ser adicionado manualmente, por exemplo, concatenar o índice para o jogo ou adicionar um movimento "final" adicional, como o último movimento possível a cada turno. Agora, isso pode levar em conta os jogadores que concederam, ou 2 consecutivos para indicar que os jogadores concordaram com um empate. Isso só é necessário se o jogo não terminar em xeque-mate ou impasse com base na posição, neste caso, está implícito. Nesse caso, ele eleva o número de bits necessários em média para 356 e, no pior caso, 1762.


1
Seu argumento de "amortização" não funciona. O objetivo é codificar uma placa fornecida pelo usuário. Você não pode dividir o custo de codificação desta placa entre as 400 placas auxiliares que você pode gerar ao longo do caminho. (Isso só seria aceitável se esses 400 tabuleiros fossem escolhidos de forma independente pelo usuário, e não limitados pelo requisito de formar um jogo de xadrez.) Além disso, um jogo de xadrez pode teoricamente fazer muitos milhares de movimentos , e o OP é claro sobre o interesse pelo pior caso.
Anders Kaseorg

@ AndersKaseorg: Muito verdade. Realmente depende do objetivo. Se você está tentando armazenar um jogo inteiro com todos os outros algoritmos, seriam necessários m * c bytes, em que m é o número de jogadas ec é o tamanho da saída. Então, se você está tentando armazenar um jogo inteiro de 80 movimentos usando a solução de 160 bits, seriam necessários 12800 bits enquanto os meus apenas 351. Para o bem da concorrência, admito que você esteja correto, mas achei uma propriedade legal salientar, uma vez que é muito comum querer armazenar jogos inteiros e não apenas tabuleiros.
Edggy

O objetivo é inequívoco. “O objetivo é fazer a menor representação de um tabuleiro de xadrez que possa ser usado (uma vez decodificado) para determinar todas as possibilidades de movimento de um jogador nesse turno. … Sua pontuação é determinada no pior cenário possível - tamanho máximo possível em bits. ”
Anders Kaseorg 16/07/19

@ AndersKaseorg: Eu nunca afirmei que era ambíguo. Eu apenas decidi adotar uma abordagem diferente. Uma coisa a notar é que, para encontrar a menor placa usando meu algoritmo, preciso do menor caminho para chegar a essa posição. Por exemplo, no jogo de turnos de 11741 que você vinculou para chegar à mesma posição no tabuleiro, não preciso seguir esse caminho se tudo que nos interessa é o tabuleiro. Então, para codificar o jogo vinculado, apenas encontro o jogo mais curto que resta com 2 reis naqueles quadrados que podem ter apenas 200 turnos ou menos. Isso pode ser feito com uma pesquisa aprofundada.
Edggy

Usar um jogo equivalente mais curto é bom, se você puder provar que todas as posições são alcançáveis ​​em 200 turnos ou menos (no momento, isso parece apenas um palpite). Você também precisará contabilizar posições de xadrez com mais de 100 jogadas legais , a menos que possa provar que elas não surgem em sua construção. Dividir seu resultado pelo número de jogadas no jogo ainda não é permitido pelas regras deste desafio.
Anders Kaseorg 16/07
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.