Minima compressione della scacchiera


39

Scrivi un algoritmo o un programma in grado di codificare e decodificare una scacchiera. L'obiettivo è quello di creare la più piccola rappresentazione di una scacchiera che possa essere usata (una volta decodificata) per determinare tutte le possibilità di movimento per un giocatore in quel turno.

La codifica deve essere in grado di mostrare:

  • Di chi è il turno.
  • Se il giocatore può castellare su ogni lato.
  • Se il giocatore può eseguire un en-passant e, in tal caso, quale delle sue pedine?
  • Posizioni di tutti i pezzi.

Nota importante sul castling: se il bianco sposta il proprio re di un turno, e poi lo sposta indietro di nuovo il successivo, deve essere chiaro che non potranno più castello da nessuna parte. Lo stesso andrebbe se spostassero la loro torre sinistra o destra. Sebbene il tabellone sia visivamente nello stesso stato di due turni fa, lo stato del gioco è cambiato. Maggiori informazioni qui: http://en.wikipedia.org/wiki/Chess#Castling

Nota importante su en-passant: anche questa è una mossa sensibile al turno. Leggi le regole per maggiori informazioni. http://en.wikipedia.org/wiki/Chess#En_passant

Determinare input e output secondo necessità. Principali oggetti di scena per chi può comprimerlo di più!

Il tuo punteggio è determinato nel caso peggiore: la massima dimensione possibile in bit. Assicurati di mostrare come l'hai calcolato quel numero e ciò che hai rappresentato. Spara per il più piccolo caso peggiore!


Cosa intendi con "bit a bit"?
Peter Taylor,

Questo codice è più piccolo o più compresso? Più compresso è più interessante.
Justin il

Ci scusiamo per non aver chiarito. Bit a bit, nel senso che puoi comprimerlo solo se inizi a rappresentarlo come bit, il che richiederà alcune operazioni a bit. Scarso uso da parte mia. Anche il codice più compresso, non il più piccolo.
Seltzer,

2
@GeekWithALife Sì, è possibile avere 18 regine contemporaneamente sulla scheda. Segui questo link e fai clic sul pulsante di riproduzione per un esempio.
ossifrage schifoso

1
@AJMansfield, che potrebbe essere utile per le board con circa 28 uomini, ma ho calcolato che 117 bit sono sufficienti per le board con tutti i 32 uomini, che è circa 50 bit in meno rispetto al target. La complicazione è che una volta scesi sotto i 32 uomini, la promozione può dare a un giocatore più vescovi.
Peter Taylor,

Risposte:


27

Min: 12 bit
Max:
Media:

Ieri sera avevo pensato che avrei potuto renderlo ancora più piccolo.

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)

Il risultato è una dimensione impressionante di 12 bit !

E che dire di K +1 altro tipo di pezzo?

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

Ci 2 possibili disposizioni dell'albero secondario.

   /\      /\
  +  K    K  +

Entrambi danno le stesse dimensioni di bit per tutti i pezzi. Quindi non fa alcuna differenza a quale usiamo, sceglierò il primo.

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

Quindi su King +2 altri tipi di pezzi

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

Ci sono 5 possibili sottoalberi (userò 1 e 2 per indicare quale dei pezzi.)

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

Quindi avremo bisogno di 3 bit per codificare quale sottoalbero usare.

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

Sto ancora facendo l'analisi per altri pezzi

+3 Altro

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

+4 Altro

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

+5 Altro

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

Max: 208?


È possibile codificare tutti questi sottoalberi in 9 bit?

Se sommiamo tutti i possibili sottoalberi otteniamo 392 possibili sottoalberi.

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

Usando l'ID Freq

Da allora 164603 frequenze dei pezzi uniche .

Log2( 164603) = 17.3286110452
             ~ 18 bits

0
 0000 0000 0000 0000 00  Freq ID

(+000) (+00) Castling

Max: = 204 bit


rev 3

Min: 82 Max: 199 Media: 160

Finalmente ho fatto qualche analisi per trovare la dimensione massima dei bit. Con una codifica huffman ottimale per ciascuna delle frequenze pezzo uniche .

               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 

Nota che questa è la dimensione peggiore possibile, che la colonna En-Passant inserisce se il numero di pedine è maggiore di uno. Indipendentemente dai colori e dalla posizione di questi pedoni, è possibile che alcune schede siano più piccole di 3 bit.

Inoltre ci sono solo 144 dimensioni diverse (Peggior caso) per le dimensioni della scheda.


75 - 216 bit (v2) v1 La dimensione minima è 98 bit (12,25 byte), solo i due re sulla scheda.

La dimensione massima è di soli 216 bit (27 byte). Al contrario:

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

In media la dimensione sarà di circa 157 bit (19.625 byte).

pezzi

Per codificare la scheda sto usando uno schema di codifica ad albero binario. Un quadrato vuoto è il più frequente da qualsiasi luogo tra 32 e 62 presenze. Poi ci sono i pedoni, poi Corvi, Cavalieri, Vescovi e i meno frequenti sono la Regina e il Re.

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

La scheda di partenza può essere codificata in soli 166 bit (20,75 byte)

  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

Per indicare chi si muove richiede solo un singolo bit

0-> Black , 1-> White

Il castling può essere codificato in 4 bit.

 B  W
LR LR
00 00

Quindi ho usato 171 bit (21.375 byte)

En-Passe può essere codificato in soli 16 bit (2 byte)

Quindi in totale questo è 187 bit (23.375 byte).

disposizione

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

Non ho ancora scritto alcun codice.

Si noti che 3 dei bit non utilizzati. Quindi il massimo è 213 bit .


Possibili miglioramenti

1) Ridotto il blocco di intestazione da 24 a 8 bit (con suggerimento di @Peter Taylor)

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

2) Intestazione a lunghezza variabile

Una piccola intestazione fissa a 4 bit

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

Blocco successivo di bit aggiuntivi (se è ancora possibile il castling)

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

Prossimo blocco di bit aggiuntivi (se sono presenti pedine)

000--> En-Passant column Position

Quindi ora ho un'intestazione a lunghezza variabile 4 - 11 bit


3) Utilizzare uno schema di codifica diverso a seconda dei pezzi lasciati sul tabellone.

Modificando la codifica dell'albero in base ai pezzi presenti sulla scacchiera e alla relativa frequenza.

Una possibile codifica per uno stato di fine gioco (No Pawns)

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

Che è di circa ~ 4 bit per pezzo.

Che tipo di pezzi sono presenti sul tabellone?

RBNQK Permutation
11111 (11111)

La permutazione è di lunghezza variabile 0-5 bit. Se rimane solo un tipo di pezzo, non includerlo.

Quale permutazione di quei pezzi usare per l'albero? Questo è il fattoriale del numero di pezzi nell'esempio sopra, sono 5 pezzi, quindi 120 possibili permutazioni che possono essere codificate.

 #    !  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.

Ricorda che ci sono bit di aggiunta per i quadrati e il colore vuoti.


Esempi

Facciamo un esempio del solo QK rimasto

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

81 bit in totale


Diamo un esempio dei soli re rimasti

 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

Metti tutti insieme

 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

Quindi calcolo la codifica più piccola per la scheda a 75 bit (9 bit 3 bit)

Ancora da calcolare in che modo questo schema di codifica influisce sulla dimensione massima.


Miglioramento 4

Ridurre il numero di bit per il castling a soli 2 bit. Basta cercare il giocatore che è il turno.

 0 Castling possible (from header block)
 LR 
 00

Pensandoci, forse è meglio includere solo i 2 bit all'interno del blocco di intestazione.


Non sono necessari 16 bit per en passant. Al massimo un pedone spostato nell'ultimo giro, quindi sono sufficienti quattro bit (ad esempio 1111per "nessun en passant possibile" o la colonna come numero binario altrimenti).
Peter Taylor,

Perché i pedoni ottengono una posizione migliore in un albero? Nel caso comune sono più comuni, ma in casi estremi R / B / N può apparire 10 volte.
Ugoren,

@PeterTaylor, in realtà 3 bit sono sufficienti per en passant. Se conti solo le colonne con una pedina di 5 ° grado nera (supponendo che si sposti in bianco), 8 diventa non valido.
ugoren,

1
Nota che il tuo caso peggiore non è in realtà possibile. La promozione è impossibile senza acquisizioni (è necessaria almeno un'acquisizione per 2 promozioni).
ugoren,

2
Nota per codificare 64 posizioni (per re bianco o nero) sono necessari 6 bit (2 ** 6 = 64).
lambruscoAcido,

17

192 bit (caso peggiore)

Ecco uno schema di archiviazione molto semplice che dovrebbe far fronte a promozioni di pedine arbitrarie e che non richiede mai più di 64 + 4 × 32 = 192 bit:

  • I primi 64 bit memorizzano un bitboard che dice dove sono i pezzi (ma non quello che sono). Cioè, memorizziamo un bit per ogni quadrato della scacchiera (iniziando dal quadrato a1, quindi b1, c1, ecc. Fino al quadrato h8) in modo tale che un quadrato vuoto sia rappresentato da 0 e un quadrato occupato da 1.

  • Successivamente, per ciascuno dei quadrati contrassegnati come occupati sul bitboard, memorizziamo un bocconcino a 4 bit che codifica il pezzo su quel quadrato. Il primo dei quattro bit codifica il colore del pezzo (0 = bianco, 1 = nero), mentre i restanti tre bit codificano il tipo di pezzo:

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

    Tipo di pezzo

    0 = pedina (normale)
    1 = torre (normale)
    2 = cavaliere
    3 = vescovo
    4 = regina
    5 = re (del giocatore che si sposta successivamente)
    6 = re (dell'altro giocatore)

    Nota le due codifiche per il re, usate per determinare quale turno del giocatore deve muovere. (Infatti, poiché ci sono sempre due re sulla scacchiera, che consentono quattro combinazioni dei codici 5 e 6, potremmo piuttosto facilmente codificare qui un secondo bit di informazioni.)

    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                     |
    +----+----+--------------------------------+
    

    Per codificare le informazioni extra necessarie per le regole en passant e castling, introduciamo un tipo di pezzo aggiuntivo, che indica una pedina o una torre a seconda della riga in cui appare:

    7 (nelle righe 1 e 8) = una torre che non si è mai mossa, e il cui re non si è mai mosso, e che quindi è ammissibile al castling
    7 (nelle righe 4 e 5) = una pedina che ha appena avanzato di due quadrati, e può quindi essere catturato en passant

Mettere tutto insieme:

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

Il numero totale di bit necessari per codificare lo stato della scheda è quindi 64 + 4 × # di pezzi sulla scheda. Dal momento che non ci possono mai essere più di 32 pezzi sulla scheda, la lunghezza massima di questa codifica è di 192 bit.

Ad esempio, utilizzando la codifica sopra descritta, lo stato iniziale della scheda verrebbe codificato come (spazio bianco inserito per leggibilità):

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

o, in esadecimale:

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

2
"pedina che ha appena avanzato due quadrati" e "torre che non si è mai mossa" potrebbero condividere lo stesso slot di stato poiché si escludono a vicenda a seconda della riga in cui si trovano. Lo stato extra free può essere usato per codificare "re del colore di chi è il turno"; dovresti essere in grado di sbarazzarti della parte penzolante in quel modo.
FireFly,

È anche possibile salvare un po 'memorizzando solo 63 bit per il bitboard e inferendo l'ultimo bit dal numero di uomini codificati. (Non mi è chiaro se si tratti di barare o meno, perché richiede una codifica esterna della lunghezza della sequenza di bit). E se elimini gli stati 6 e 7 per gli uomini devi codificare fino a 6 ^ 32, che richiede 82,7 bit; arrotondando a 83 si risparmia 13 bit utilizzando gli stati 6 e 7 e si possono codificare le stesse informazioni in soli 8 bit.
Peter Taylor,

Grazie, @FireFly! Ho implementato il tuo suggerimento. (Il suggerimento di Peter Taylor è ancora più efficiente, ovviamente, ma non l'ho usato finora perché mi piace un po 'la semplice codifica binaria dello schema corrente. Potresti sempre inviarlo come voce separata ...)
Ilmari Karonen,

Va bene - questo è leggermente complicato. Ma ascoltami. Se prendi semplicemente il colpo di 1 bit su un indicatore di svolta, puoi sostituire il re con il turno con un pezzo che chiamo pedone1. Cambia pedone in pedone0. Ora, ogni volta che c'è una pedina (non en passant vulnerable) - ottieni anche un po 'di informazioni sul pezzo successivo (o 0 per pawn0 o 1 per pawn1). Poiché ci sono 16 pedine, ottieni 16 bit in meno 1 per l'indicatore di svolta. Ogni volta che c'è un pedone che è vulnerabile all'en passant, devi aggiungerne un altro dopo. Ma come en passant deve accadere immediatamente, i tuoi guadagni minimi sono di 14 bit.
user5957401

Potresti anche fare una cosa simile con qualcosa come i vescovi. Supponiamo di avere un vescovo non nella sua "zona speciale" (i 10 punti ai suoi angoli e la fila centrale sul lato) sono contrassegnati come speciali. Perché conosci la sua posizione, sai che è un vescovo. Ora hai due vescovi e potresti dare a ciascuno di loro uno 0 o 1 sul pezzo successivo. Questo dà altri 4 bit, ma il caso peggiore ha vescovi in ​​tutte le zone speciali e nessun guadagno.
user5957401

14

Il peggior caso di 160 bit

Dopo aver pubblicato la mia precedente risposta a 22 byte, ho iniziato a chiedermi se potevamo scendere a 21 byte. Tuttavia, quando ho visto gli incredibili 166 byte di Peter Taylor, ho pensato "Aspetta, sembra che siano possibili cinque parole a 32 bit!"

Quindi, dopo un bel po 'di pensiero, ho pensato a questo: 159.91936391 byte (una misura abbastanza stretta!) Questo livello di compressione avrebbe bisogno di un programma abbastanza complicato, ma ho pensato a come farlo funzionare in tempi ragionevoli.

Questo sarà un post lungo, quindi per favore abbi pazienza con me, posterò quello che posso oggi e aggiungerò presto alcuni bit di codice.

Quindi, ecco come farlo:

En Passant e castling codificati da posizioni illegali (0 bit)

En Passant

Come menzionato in altre risposte, ci sono un massimo di 5 quadrati possibili su cui può stare una pedina vulnerabile a un passante. Questi sono i quadrati accanto alle pedine del giocatore di cui è il turno.

Per codificare questo, il pedone vulnerabile a en passant viene scambiato con qualunque cosa si trovi su uno dei quadrati nella prima o nell'ultima riga. Questo può essere un uomo o un quadrato vuoto. Questo produce una posizione illegale, poiché i pedoni non possono essere su queste file. Il decodificatore deve riportare il pedone nella posizione corretta, estraendo le informazioni en passant.

Affinché ciò non interferisca con la codifica castling, è importante che i quadrati su cui si trovano i re all'inizio del gioco non siano disturbati e che la procedura di codifica en passant non posizioni i re uno accanto all'altro, quale sarebbe una posizione re illegale. Per soddisfare il secondo di questi punti, l'encoder ha due scelte su quale quadrato scambia il pedone en passant. Il quadrato di prima scelta per ciascuna delle fino a 5 pedine è A8, B8, C8, G8, H8. Seconda scelta: A1, B1, C1, G1, H1.

arrocco

Un re a cui è permesso fortificare è per definizione, ancora nella sua piazza iniziale. Con il re bianco nella sua casella iniziale, ci sono un totale di 63 quadrati in cui il re nero può stare, 58 dei quali sono legali (non gli è permesso di muoversi proprio accanto al re bianco perché si metterebbe sotto controllo). Se il re bianco è autorizzato a fortificare, è autorizzato a fortificare con la sua torre sinistra, la sua torre destra o entrambi. Vi sono quindi 3x58 = 174 possibilità in cui il re bianco può fortificare, un altro 174 in cui il re nero può fortificare e un altro 3x3 = 9 in cui entrambi possono fortificare, per un totale di 357.

Ci sono 420 arrangiamenti illegali dei due re in cui si trovano su quadrati adiacenti: 3x4 = 12 quando il re bianco è nell'angolo, 5x24 = 120 quando è sul bordo e 8x36 = 288 quando è su un altro quadrato. Quindi ci sono abbastanza posizioni illegali per codificare tutte le possibili possibilità di castling.

Se almeno un re è autorizzato a castellare, l'encoder cercherebbe i dati di castling e i dati di posizione di quei re non autorizzati a castellare in una tabella (o, in alternativa, utilizzare un algoritmo che non specificherò qui) e produrrebbe posizione dei due re. Quindi scambiava i re con qualunque cosa fosse accaduta su questi quadrati.

È importante che questo sia codificato e decodificato prima dell'en passant, altrimenti ci sono alcune potenziali interferenze.

Confronto

Quindi, finora non ho usato bit! Guardando la risposta di Peter, devo ancora codificare:

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

Questo è per il caso peggiore di 29 uomini (vedi la risposta di Peter). Di seguito mostrerò come faccio un miglioramento marginale (almeno per il caso di 29 uomini) su entrambi i punti segnati in **.

Quali quadrati sono occupati / di chi è il turno?

Il modo più semplice per codificare quali quadrati sono occupati è con una griglia a 64 bit. Questo ci dice anche quanti quadrati sono occupati. Tuttavia è un po 'dispendioso perché non è possibile occupare più di 32 quadrati. La mia soluzione è usare 1 per codificare per i quadrati occupati quando è il turno di White e 0 per codificare per i quadrati occupati quando è il turno di Black. Ora vengono utilizzate tutte le combinazioni e non ci sono rifiuti.

Quindi risparmiamo un po 'per memorizzare il turno: meno di 32 1, è il turno del bianco, più di 32 1, è il turno del nero. L'unico caso ambiguo è quando tutti gli uomini sono sul tabellone e ci sono 32 1 e 32 0. Pertanto è necessario un bit in più solo per questo caso. Poiché non ci possono essere promozioni fino a quando non si è verificata una cattura, questo bit in più non influisce sul caso peggiore in generale (che si verifica con 3 uomini catturati e 29 rimasti).

Colore degli uomini che occupano i quadrati

Sappiamo da sopra quanti uomini ci sono. Il seguente estratto del triangolo di Pascal racconta quante possibilità ci sono per le diverse distribuzioni di bianco e nero. Ad esempio, per 3 uomini, le possibilità sono: 3 uomini neri (1 permutazione) 2 neri, 1 bianco, (3 permutazioni), 1 nero, 2 bianchi (3 permutazioni), 3 bianchi (1 permutazione). Il totale è 2 3 = 8. In generale, per il numero inferiore di uomini ci sono 2 n possibilità. Tuttavia tutte le possibilità tutto nero e tutto bianco sono illegali (almeno il re di ogni parte deve essere sul tabellone), quindi il numero effettivo di permutazioni legali è 2 n -2 (ignora gli 1 sul triangolo Pascal).

Per più di 16 uomini in totale, c'è un ulteriore vincolo in quanto non ci possono essere più di 16 uomini di ogni colore sul tabellone. Pertanto, quando tutti e 32 gli uomini sono sul tavolo, ce ne devono essere 16 ciascuno e il numero totale di possibilità è 601080390, che è un po 'meno di 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

Il numero di possibilità può essere trovato sommando le "righe" di questo estratto del triangolo di Pascal (per cui intendo le diagonali NE-SW della tabella, perché ho ruotato il triangolo di 45 gradi in senso antiorario per una comoda presentazione. Il numero di bit necessari codificare il turno, i quadrati occupati e il colore degli uomini è quindi il seguente:

Fino a 25 uomini: poco meno di 64+ (numero di uomini)
Per più di 25 uomini:

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

Per i due colori, quali uomini e in quale ordine?

Come per le risposte precedenti, nessuna pedina può essere promossa fino a quando non si è verificata una cattura, poiché ogni pedina è bloccata da una pedina di colore opposto sulla stessa colonna. La risposta di Peter considerava (come limite superiore) che ogni acquisizione poteva portare a una promozione per il lato catturato e due per il lato che cattura. Tuttavia, possiamo dividerlo in diversi casi:

  1. Il pedone nero cattura il pedone bianco: ora il pedone di cattura è libero di essere promosso poiché ora si trova su un'altra colonna. Anche il suo collega sulla stessa colonna può promuovere. Il pedone nero sulla colonna originale del pedone bianco può anche promuovere. Questo è l'unico caso che consente 3 promozioni.

  2. Il pedone nero supera il pedone bianco sulla colonna adiacente e quindi cattura il pezzo bianco (diverso dal pedone) dietro. Ciò consente la promozione del pedone di cattura e del pedone bianco che si trovavano nella colonna originale. Una promozione per ogni parte.

  3. Il pedone bianco viene catturato per pezzo (diverso dal pedone). Ciò consentirebbe normalmente una promozione solo per il nero. L'unica eccezione è quando libera una formazione di pedine bloccata che era già stata causata da diverse catture che spostavano pedine sulla stessa colonna.

Quindi, come base, possiamo considerare che ogni acquisizione consente una promozione a testa per entrambe le parti. Nel caso in cui l'uomo catturato sia una pedina, potrebbe esserci una promozione aggiuntiva per il lato di cattura.

Ho scritto un programma simile a quello di Peter. È un po 'più rozzo, ma ha un'aggiunta importante: può calcolare il numero di permutazioni possibili quando un giocatore inizia con meno delle normali 8 pedine. Ecco alcuni dati prodotti dal programma:

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

Possiamo vedere che per un caso come 8 pedine, 15 uomini, 0 promozioni, il numero di permutazioni è solo leggermente inferiore rispetto a 8 pedine 16 uomini, 0 promozioni. Tuttavia se consideriamo un caso come 7 pedine, 15 uomini, 0 promozioni (il che equivale a considerare che l'uomo catturato era sicuramente un pedone) otteniamo circa la metà del numero di permutazioni.

Quindi, nel caso in cui il Nero abbia 16 uomini e il bianco abbia 15 uomini, possiamo considerare una stima con limite superiore di 2 promozioni per il Nero e una promozione per il Bianco:

5383778400 x 660810150 = 3.55766E+18 possibilities

Tuttavia possiamo fare di meglio se procediamo come segue.

A. Prendi in considerazione una promozione ciascuna per il bianco e nero, supponendo che l'uomo che il bianco ha perso possa essere di qualsiasi tipo:

843242400 x 660810150 = 5.57223E+17 possibilities

B. Considera le possibilità aggiuntive per il Nero se ha due promozioni, moltiplicate solo per quelle possibilità per il Bianco in cui ha perso una pedina.

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

Sommando questi due insieme otteniamo 2.25072E + 18, che è un numero inferiore a 3.55766E + 18. Di seguito sono elencate tutte le possibilità per un massimo di 3 catture (29 uomini rimanenti).

(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

Quindi, nel caso peggiore di una parte con 15 uomini e l'altra con 14 uomini, abbiamo bisogno di 67.804 bit.

Aggiungendo questo ai 92.116 bit richiesti per specificare quali quadrati e quale colore, otteniamo un totale di 67.804 + 92.116 = 159.92 bit.


1
Mille grazie a @Einacio per aver cambiato le virgole decimali in punti decimali. Ho fatto molti dei miei tavoli su Excel su un computer spagnolo, e pubblicare questo è stato un grande lavoro, quindi risolvere questo è stato qualcosa che ho lasciato per dopo. Come ho già detto, non ho ancora finito questo post, aggiungerò il mio programma di conteggio delle permutazioni e alcuni frammenti di codice sulla codifica / decodifica quando avrò tempo. PS. Non avevo idea che così tante persone stessero leggendo questo :-)
Level River St

alla fine sei riuscito a prendere dei byte invece dei bit che è la cosa che volevi dire, che potrebbe causare un po 'di confusione ai lettori
masterX244,

13

Il peggior caso di 177 bit

Questo algoritmo, sebbene difficilmente semplice, fornisce uno scenario peggiore di 177 bit (184b = 23B in pratica), 13b (16b = 2B) nel caso migliore quando rimangono solo 2 re.

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

Molto bella. Puoi renderlo ancora più efficiente sostituendo i bit 14-105 (92 bit) con una codifica basata su coefficienti multinomiali. sum_{i=0}^{15} sum_{j=0}^{15} 62! / (i! j! (62-i-j)!) < 2^87.45.
Peter Taylor,

L'unica cosa che vorrei cambiare è creare una versione piuttosto più semplificata per l'area circostante. Ad esempio: se si codificano i 30 pezzi nella base 5 e ci sono un massimo di 5 posizioni secondarie, è possibile avere 5 ^ 31 <2 ^ 72. Come se li dividessi in enpassant (13) e non-enpassant (59), ma senza ulteriore complessità.
Alin Stoian,

In questo modo verrebbe effettivamente utilizzato 1 bit in più. Il motivo è che ci possono essere (nel peggiore dei casi) 5 possibilità possibili, ma ho ancora bisogno di dichiarare la possibilità di "nessun soggetto", ovvero un sesto stato. Il 1 bit in più in questo caso andrebbe a dichiarare possibile o meno un enpassant (e con questo approccio potrei anche usare un approccio ancora più semplice con la codifica dei 30 pezzi saltando il blocco enpassant e usare 3 bit separatamente per il controllo enpassant, che porta anche all'utilizzo di +1 bit). La seguente quinta fila consentirebbe 5 potenziali avventurieri (turno di White): BWBBWBBW
FIQ

sì hai ragione.
Alin Stoian,

7

166 bit

  • 1 bit: chi è il turno?
  • 2bit: quali opzioni di castling sono aperte? (NB alla lettura ravvicinata della domanda, è necessario solo registrare le opzioni di castling per il giocatore di cui è il turno).
  • lg 6 ~= 2.585bit: quali opzioni en passant sono aperte? (Vedi la mia altra risposta)
  • lg sum_{i=1}^{16} sum_{j=1}^{16} 64! / (i! j! (64-i-j)! = lg 3629590441720924477681996172 ~= 91.552 pezzi: quali quadrati sono occupati da uomini di quale colore?
  • Nel peggiore dei casi lg 451366131803622235200 ~= 68.613per indicare quali uomini e in quale ordine (vedi sotto)

Usando la codifica aritmetica (poiché ad ogni passo stiamo applicando una distribuzione uniforme) possiamo raggiungere ceil(3 + 2.585 + 91.552 + 68.613) = 166 bit.

La codifica per gli uomini: dato che sappiamo quanti uomini di un determinato colore ci sono, possiamo facilmente enumerare tutte le possibili distribuzioni / multiset di uomini (ad esempio con 5 uomini potremmo avere un re, una regina, due torri e un Pawn) e quindi possiamo considerare tutte le possibili permutazioni di ogni distribuzione.

Tuttavia, possiamo fare ancora meglio tenendo conto delle interdipendenze. Lo sto facendo solo a un livello molto semplice: quante possibili promozioni? Una pedina può solo diventare "superata" e in grado di promuovere in tre modi: cattura e quindi si sposta in una colonna diversa; o il suo pedone opposto cattura e quindi si sposta in una colonna diversa; o la sua pedina avversaria viene catturata. Pertanto, una cattura per il bianco crea potenzialmente due pedine passate per il bianco e una per il nero.

Possiamo costruire una tabella parziale dei limiti superiori per le promozioni:

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

Possiamo anche calcolare il numero di permutazioni dato che un giocatore ha Nuomini e non più di Ppedine promosse:

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 i due, possiamo ottenere il numero di bit necessari per specificare entrambe le permutazioni dato il numero di uomini su entrambi i lati:

           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 non è in questa sezione del tavolo, possiamo solo supporre che entrambe le parti abbiano fino a 8 promozioni e stiamo ancora facendo meglio del caso peggiore, che è 68.613 bit quando uno ha 14 uomini e l'altro ha 15 uomini.

Si noti che questo è ancora molto lontano dall'essere una rappresentazione perfetta, perché consente molte posizioni illegali.

Codice per il calcolo della tabella di permutazione:

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();
        }

    }
}

Come deduci le posizioni dei re? Usi 15 uomini nel tuo calcolo e nessun bit speciale per le posizioni del re.
Alin Stoian,

@AlinStoian, oops. Ho avuto un <piuttosto che <=nel loop di output del mio programma. Grazie per segnalarlo. Potrei ancora recuperare il punteggio precedente incassando tutti i 32 uomini presenti sul tabellone, ma non lo farò ora.
Peter Taylor,

Dati interessanti! Il caso peggiore teorico con 3 uomini catturati
Level River St

@steveverrill, quello che mi piacerebbe davvero fare è codificare le posizioni dei pedoni e il numero di promozioni in un "blocco" e quindi le posizioni e i valori del pezzo. Tuttavia, ci sono almeno 2 ^ 38 posizioni di pedone senza prendere in considerazione le promozioni e elencarle in modo efficiente mi è finora sfuggita.
Peter Taylor,

@petertaylor Se hai solo 16 pedine sul tabellone, limitate a 48 quadrati, hai 48! / 32! / 8! / 8! = 29019905518636890 possibilità. Poco più di 2 ^ 54! Di questi, alcuni sono illegali, non puoi avere tutte le pedine di un colore su un lato del tabellone.
Level River St

5

Caso peggiore di 178 bit (174 a pizzico!)

Ciao, sono appena tornato alla programmazione, cosa che non ho mai fatto dal college. Ho visto questo sito e ho pensato che fosse interessante. Ho fatto un piccolo controllo teorico e sembra che siano necessari almeno 146 bit per un algoritmo perfetto, probabilmente un po 'di più (spiegherò nei commenti quando avrò un momento.)

Ad ogni modo, questo è il modo in cui strutturo i dati. Il concetto di base arriva a 178 bit, ma con un po 'di jiggery pokery può essere ridotto a 174 (ovvero 21 3/4 byte). 175 è leggermente più facile da programmare, è più leggibile dall'uomo e rimane comunque entro 22 byte.

A) Posizione di entrambi i re: 6 bit ciascuno per bianchi e neri 12 bit

B) Dei rimanenti 62 quadrati, che sono occupati? Una matrice di 62 BIT

C) Di chi è la svolta? 1 BIT

TOTALE COSÌ LONTANO: 75 BIT

D) En Passant. Se è il turno del bianco di muoversi, possono sembrare catturati En Passant fino a 5 pedine nere. Il pedone nero deve essere sulla riga 5 (dal basso verso l'alto a partire da zero) e avere un pedone bianco accanto ad esso. Una situazione con il numero massimo di possibili acquisizioni è simile alla seguente:

BWBBWBBW

Se ci fossero 6 pedine nere nella riga 5, il bianco avrebbe solo 2 quadrati su cui stare e potrebbe solo minacciare 4 pedine nere, quindi non è possibile avere più di 5 pedine nere apparentemente minacciate da En passant allo stesso tempo. Quindi abbiamo bisogno di un numero da 1 a 5 che indichi quale delle (fino a 5) pedine sulla riga 5 che ha una pedina ostile (in questo caso bianca) accanto ad essa era avanzata di 2 quadrati nell'ultimo turno ( o, zero se nessuna pedina in questa situazione è stato spostato in questo modo nell'ultima curva.)

E) Tra i 30 quadrati occupati (esclusi i re) che cosa contengono?

Ci sono 10 possibilità, ognuna rappresentata da un numero decimale.

Il bit meno significativo rappresenta il colore.

Quindi i numeri pari sono bianchi, i numeri dispari sono neri.

Bianco nero

Pegno 0/1 (o Torre che è autorizzata a fortificare *)

Knight 2/3

Vescovo 4/5

Torre 6/7

Regina 8/9

* Una torre che è autorizzata a fortificare (e quindi non è mai stata spostata dalla prima o dall'ultima riga) è rappresentata da 0 o 1 anziché 6 o 7. Non può essere confusa con una pedina, perché non è possibile trovare pedine sulla prima o l'ultima riga.

Questo dà un numero decimale di massimo 30 cifre, che possiamo moltiplicare per 6 e quindi aggiungere il codice per En passant. Il numero risultante si adatterà a 103 bit, che una volta aggiunto ai 75 di cui sopra è 103 + 75 = 178 bit . In realtà, se moltiplichiamo semplicemente per 10 anziché 6, non fa alcuna differenza per il numero di bit utilizzati e la decodifica è più semplice.

Questo è solo 2 bit più di 22 byte. Tuttavia, possiamo spingerlo fino a 174 bit, come spiegato di seguito.

Se nessun pezzo è stato catturato, allora è impossibile promuovere un pedone .

La prova è la seguente. Immagina che il bianco sia ossessionato dalla promozione del suo pedone (ad esempio) nella colonna E, fin dall'inizio del gioco. C'è un pedone nero di fronte a questo pedone che si frappone. Pertanto, per promuovere questa pedina, deve accadere una delle seguenti cose:

1) Il pedone nero viene catturato.

2) Il pedone nero cattura un altro pezzo e quindi si allontana.

3) il pedone bianco cattura un pedone su una colonna adiacente come la colonna D.

4) il pedone bianco passa (o è passato da) un pedone nero su una colonna adiacente e quindi cattura un pezzo su quella stessa colonna adiacente, facendo cambiare il pedone bianco.

Il caso 4 è il più interessante, perché non è solo la pedina bianca che è iniziata sulla colonna E che ora ha un chiaro percorso di promozione. Anche il pedone nero sulla colonna che rimane sulla colonna E può essere promosso. Pertanto una singola acquisizione può spianare la strada a una pedina di ciascun colore da promuovere.

Comunque, il fatto che nessuna pedina possa promuovere fino a quando un pezzo non viene catturato significa che non dobbiamo conservare il 30 ° pezzo. Possiamo risolverlo per eliminazione (o per sottrazione, perché il set completo di codici pezzo all'inizio del gioco aggiunge sempre lo stesso importo = 80). Un punto minore è che dobbiamo garantire che i quadrati in cui si trovano le torri all'inizio del gioco sono tra i primi scansionati (perché se fossero gli ultimi, non sapremmo se il corvo potrebbe o no.) Questo è facilmente fatto scansionando la riga 0 e quindi le righe da 7 a 1: Per r = 8 a 1 riga di scansione [r mod 8].

Quindi, la matrice di bit in (B) ci dirà quanti pezzi ci sono (esclusi i re.) Se ci sono 30 interi, ignora l'ultimo pezzo durante la codifica, il decodificatore risolverà quello che era. Ora abbiamo un numero decimale di 29 cifre, che moltiplichiamo per 6 e aggiungiamo al codice En Passant. Il numero risultante verrà semplicemente compresso in 99 bit, per un totale di 99 + 75 = 174 bit.

Ad esempio Ecco una posizione reale. Il bianco ha appena fatto la sua prima mossa (pedone del re avanzato) ed è il turno del nero.

rnbqkbnr
pppppppp


    P

PPPP PPP
RNBQKBNR

A) Posizione dei re (bianco / nero in ottale, 12 bit ): 03 73 = 000011 111011

B) Quali quadrati sono occupati? Inizia con la riga zero (riga inferiore), quindi tutte le altre righe dall'alto verso il basso, saltando i re:

1111 111

1111 111
11111111
00000000
00000000
00001000
00000000
11110111 

C) Black's turn: Turn Bit = 1

D) En Passant. Non c'è pedina bianca accanto a una pedina nera, quindi non c'è pedina che può essere presa in passant (anche se questa pedina ha fatto avanzare l'ultima mossa) quindi D = 0. Se, invece di considerare solo pedine che hanno una pedina ostile accanto a loro, consideriamo tutte le pedine che non hanno pezzi amiche accanto a loro su entrambi i lati, allora D sarebbe 1, dato che c'è una pedina in questa situazione, e questo particolare il pedone fu effettivamente spostato nell'ultima curva.

E) Ancora una volta, prima la riga inferiore, quindi tutte le altre righe dall'alto verso il basso, saltando i re e con le quattro torri non registrate denominate 0 o 1 (numeri normalmente riservati per i pedoni).

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

La 30a cifra (tra parentesi) può essere scartata.

Anche se non è molto evidente qui, il pedone che White ha avanzato è in realtà a un'estremità dell'elenco dei pedoni, perché scansioniamo riga per riga.

I nostri dati ora sembrano così, con 29 codici per il contenuto dei quadrati, oltre al codice En Passant:

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

È consigliabile eseguire la scansione da destra a sinistra durante la decodifica e da sinistra a destra (ordine inverso) durante la codifica. Ciò significa che quando ci sono meno pezzi avremo un numero più piccolo, pur mantenendo la massima consistenza (cioè vogliamo che lo spazio / gli zero siano in testa, non in coda, per consentire la compressione di schede scarsamente occupate). Quando abbiamo solo 2 re sulla scheda avremo i 75 bit sopra menzionati, più 3 bit per memorizzare i dati en passant = 78 bit nel migliore dei casi. Ogni pezzo aggiuntivo è leggermente inferiore a 3,5 bit (2 pezzi possono essere memorizzati in 7 bit, perché 100 <128.)

Esiste un problema pratico in quanto un numero intero a 99 bit è troppo grande per adattarsi a una variabile intera a 64 bit, il che significa che molti linguaggi di programmazione non forniscono supporto per esso (non è possibile semplicemente convertire una rappresentazione in stringa di una cifra di 29-30 numero in un numero intero). Come modo semplice per codificare 22 byte, possiamo suddividere un numero di 30 cifre (29 codici pezzo + codice en passant) in due numeri di 15 cifre ciascuno dei quali si adatterà in 50 bit ciascuno (totale 100 bit più il 75 di cui sopra rende 175 bit peggiore.)

Per la massima compressione, come indicato sopra, 29 cifre decimali più il codice En Passant (6 possibili valori), si adatteranno quasi a 99 bit (per un totale di 174 bit) ma senza supporto dalla lingua per numeri interi di queste dimensioni è complicato da programmare. Potrebbe essere più semplice separare i 29 bit di colore e lavorare con i codici del tipo di pezzo (5 possibilità) e il codice En passant (6 possibilità) separatamente dai colori (70 bit, si adatta quasi a una variabile a 64 bit).


Bel trucco con l'ultimo uomo.
Peter Taylor,

5

Ecco una soluzione completa, il caso peggiore attuale 181 bit

Il focus qui è un semplice programma che puoi facilmente capire

L'ingresso è FEN, qui c'è la posizione di apertura, ha sei campi (5 e 6 ignorati):

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

Il primo campo (posizionamento dei pezzi) viene analizzato

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

Produrre:

rnbqkbnrpppppppp________________________________PPPPPPPPRNBQKBNR

Campo uno: codifica la posizione dei re (12 bit):

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

Campo due: codificare i pezzi (fino a 5 bit per pezzo):

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 tre: colore attivo (1 bit)

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

Campo quattro: disponibilità di castling (4 bit)

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

Campo cinque: en passant (zero o 3 bit)

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

Caso peggiore ingenuo 200 bit

  • Posizionamenti di due re - 12 bit
  • Tavola
    • QRRBBNN QQQQQQQQ - 75 bit
    • qrrbbnn qqqqqqqq - 75 bit
    • Quadrati vuoti - 30 bit
  • Colore attivo - 1 bit
  • arrocco - 4 bit
  • En Passant - 3 bit

Caso peggiore reale

Ogni giocatore non può promuovere tutte le pedine senza catturare altri pezzi . Ecco l'effetto entropia della cattura dei pezzi:

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

Quindi in realtà la scheda peggiore è:

  • QRRBBNN QQQQQQQQ - 75 bit
  • qrrbbnn qqqq - 55 bit
  • Quadrati vuoti - 34 bit

Il caso peggiore è quello di promuovere tutti i pezzi piuttosto che lasciare pedone per en passant.

TOTALE CASO PEGGIORE EFFETTIVO CON CODICE INDICATO 12 + 75 + 55 + 34 + 1 + 4 = 181 bit

FIQ mostra due miglioramenti a questo semplice schema, ma sono più difficili da codificare:

  • Rimuovi il bit 2 dalla codifica del pezzo sulle righe 1 e 8 poiché i pedoni non possono andare lì (risparmi fino a 16 bit)
  • Usa i pedoni per codificare le torri calcinabili (risparmio di 4 bit)

L'unico codice rimanente non mostrato in questa risposta (per brevità) è: interruzione dell'input FEN nei campi ( split /\s/) e assegnazione delle variabili.


Un giocatore può promuovere tutte le sue pedine (dato che è in grado di catturare le pedine nemiche); Qn4QQ / Qb6 / Qq1k4 / Qr6 / Qb6 / Qr6 / Qn4NK / RNB2B1R b - - 0 84
Krzysztof Szewczyk

@KrzysztofSzewczyk, sì, è notato sopra a PPpp=>QQq_
William Entriken,

4

Il totale dei dati richiede 33 byte

(Grazie a qualcuno nei commenti ho capito che non funziona per la promozione del pedone. Lo aggiornerò quando posso risolverlo)

per il primo byte utilizziamo cinque bit:

  • primo bit: turno del giocatore, 1 = bianco
  • secondo bit: black side side castle, 1 = can castle
  • terzo bit: castello lato regina nera, 1 = castello lattina
  • quarto bit: castello bianco lato re, 1 = castello lattina
  • quinto bit: castello bianco lato regina, 1 = castello lattina

i successivi 32 byte vengono utilizzati per rappresentare ciascun pezzo degli scacchi, in un ordine predefinito

  • 3 bit: rappresentano la riga
  • 3 bit: rappresentano la colonna
  • 1 bit: rappresenta en-passant, 1 = can en-passant
  • 1 bit: se il bit "can en-passant" è 1: indica da che parte, 0 = left
    else indica se è stato acquisito. 0 = non acquisito
    (se può essere trasferito, allora non è sicuramente catturato)

Qualche codice C per rappresentare questa idea (che in realtà non funziona)

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, questa non è una risposta ...
Maniglia della porta

1
Il tuo ordine predefinito non sarà di grande utilità quando un pedone raggiunge l'ottavo grado ed è promosso a cavaliere, vescovo, torre o regina.
ossifrage schifoso

@Doorknob of Snow ok sto lavorando all'algoritmo, è solo un po 'tardi la sera e sono stanco, quindi lo sto facendo leggermente più lentamente
pastebin.com slash 0mr8spkT

Bene, allora perché l'hai pubblicato se non hai nemmeno una soluzione?
Maniglia della porta

3
se continui a pensare che questa risposta sia una schifezza e non abbia alcun valore qui, vai avanti e vota per eliminarla e ridimensionarla e puoi anche cancellare il mio account qui. voglio solo condividere ciò a cui potrei pensare, perché voi ragazzi dovete essere così cattivi?
pastebin.com slash 0mr8spkT

4

256 242 bit

Ecco un algoritmo di compressione di base che può essere probabilmente migliorato perché non esclude la rappresentazione di determinate posizioni illegali.

La scheda inizia con 5 bit di informazioni di intestazione, come segue:

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

Quindi, una stringa di 12 bit che rappresentano le posizioni dei re.

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

Quindi, un enorme numero di 64 cifre nella base 11, che viene quindi moltiplicato per 9 per aggiungere un'altra cifra alla fine che rappresenta lo stato di en-passant. Ogni cifra nella base 11 rappresenta un quadrato sul tabellone, con i seguenti valori possibili:

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 le cifre in base 9:

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

11 64 × 9 è circa 224,57 , che richiede 225 bit per codificare. Inoltre, i 17 bit di intestazione nella parte superiore rappresentano un totale di 242 bit.


Grazie a ugoren per i miglioramenti.


Questo è molto simile all'algoritmo dell'asso, ma utilizza le posizioni della scacchiera anziché i pezzi in un ordine predeterminato, che lo esclude dal problema di promozione del pedone e consente di tagliare un po 'i dati.
Joe Z.

Puoi salvare en-passant come un numero compreso tra 0 e 8 (su quale colonna il giocatore corrente può catturare en-passant?). 13^64 * 9è 239,99, risparmiando 11 bit. Risparmia di più codificando le posizioni del re separatamente.
Ugoren,

Secondo Doorknob of Snow che ha commentato il mio post, questo tipo di risposta non è "una risposta". Sto solo dicendo. Cordiali saluti, il suo commento è stato pubblicato prima di aggiungere il codice C alla mia risposta.
pastebin.com slash 0mr8spkT

@ugoren: me ne sono dimenticato. Hai ragione, ho dimenticato che solo un pedone può essere en-passant allo stesso tempo.
Joe Z.

@ace: la tua risposta non è valida perché non include il codice di codifica e decodifica; non è valido perché non tiene conto del caso di promozione del pedone (nel qual caso il tuo ordine predefinito di pezzi non fa nulla). Il problema, in sostanza, richiede uno schema di codifica dei dati. Il programma è solo qualcosa per interfacciarsi con quello.
Joe Z.

3

? bit

(≥ 217 nel peggiore dei casi, 17 nel migliore dei casi, 179 per la scheda iniziale)


Descrizione della codifica

I metadati extra sono costituiti da chi è il turno (un bit) e da castling (quattro bit, vale a dire castello bianco dalla parte dei re? Dalla parte delle regine? E similmente per il nero).

Per la posizione della scheda stessa, la codifichiamo come un insieme di pezzi attivi. Bene, in realtà, ci assicuriamo di elencare i pezzi in un ordine particolare per ragioni che spiegherò tra poco. Per ogni pezzo memorizziamo il suo colore (un bit), il suo tipo (tre bit per comprendere 6 tipi, più un tipo in più per "pedone che può essere preso da en passant"), così come la sua posizione.

Ecco la parte interessante: per codificare la posizione di un pezzo, invece di memorizzarlo come coordinata, memorizziamo la sua distanza relativa dall'ultimo pezzo quando si enumerano i pezzi in ordine da sinistra a destra, dall'alto verso il basso (cioè A8 , B8, ..., G1, H1). Inoltre, memorizziamo la distanza come un numero a lunghezza variabile, usando 1per indicare che questo pezzo è proprio accanto al precedente, 0xxper saltare 1-3 pezzi, 000xxxper saltare 4-10 pezzi, 000000xxxxper 11-25, 0000000000xxxxxper 26-56 e infine 000000000000000xxxper 57-62.

Esempi

Ho fatto una sintesi di alcune posizioni codificate con questa codifica e ho annotato quella per la posizione iniziale con alcuni commenti.

Non so come analizzare la dimensione del bit nel caso peggiore, ma andando dagli esempi in sintesi, credo che l'algoritmo dovrebbe essere almeno in qualche modo efficiente.


Implementazione del decodificatore

Di seguito è riportato un decodificatore rapido e sporco per questa codifica (prendendo come input i dati binari codificati nel testo, come nell'esempio annotato sopra, e saltando cose che non sono '0' o '1'). Produce una scacchiera unicode su 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;
}

Non ho idea di quale sia il numero di bit nel caso peggiore, ma sospetto che sia considerevolmente più di 179 bit. Ad esempio, come gestirà il tuo algoritmo questo layout ? (A proposito, è valido; l'ho fatto usando l'editor di chess.com )
squeamish ossifrage

@squeamishossifrage che sembra richiedere 217 bit: gist.github.com/FireyFly/8639791 (grazie per il test-case, volevo provarlo con uno più complicato!)
FireFly,

Ehi, non è male. Continua così!
ossifrage schifoso

2

Max: 184 bit, Min: 75 bit

Sono stato ispirato dalla codifica Huffman di @ AdamSpeight per pezzi per provare a creare il mio schema. Dubito che questo vincerà, ma ha limiti calcolabili.

Questo schema tratta i pezzi degli scacchi come se ci fossero 11 diversi tipi di pezzi. Ho seguito approssimativamente l'algoritmo di codifica Huffman per raggruppare queste classi in base alle loro frequenze e ai tipi reali per generare le seguenti codifiche:

 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

Il codice di ogni pezzo può essere preceduto da due bit per mostrare a quale squadra appartiene ( 10per il bianco, 11per il nero). 0può essere usato per codificare spazi vuoti. Queste idee ci consentono di costruire una codifica quadrato per quadrato per l'intera scheda usando la procedura che vogliamo. Assumerò l'ordine di iterazione a1, b1, c1, ... f8, g8, h8. Ciò significa che elencare questi codici come mostrato sopra codifica tutte le informazioni tranne il turno di cui si tratta. Un motore di scacchi molto semplice può usare le "classi" per pedine, torri e re per determinare se castling e en passant sono legali. Inoltre, questo schema gestisce facilmente le promozioni dei pegni. Se un giocatore promuove una pedina in una torre, si possono usare i codici lato re o lato regina fintanto che viene scelta la variante "mossa".

Ad eccezione delle posizioni patologiche che non credo possano mai accadere, lo scenario peggiore per questa codifica è quando tutti i pezzi sono ancora sul tabellone e il giocatore precedente ha spostato una pedina in avanti di due spazi. Ad esempio, la scheda seguente codifica1. 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

Ciò significa che la codifica nel caso peggiore ha 184 bit: 1 per indicare il giocatore, 32 per gli spazi vuoti, 45 per i pedoni impassibili, 6 per il pedone a due spazi, 24 per i cavalieri, 24 per i vescovi, 28 per i corvi, 12 per le regine e 12 per i re.

Man mano che i pezzi si spostano e vengono catturati, la dimensione della codifica diminuirà. Lo scenario migliore è rappresentato da due soli re sul tabellone: ​​1 bit per indicare il giocatore + 62 bit per indicare i quadrati vuoti + 12 bit per indicare i re fornisce una lunghezza minima di 75 bit.

Tornerò e modificherò questa risposta con un po 'di codice che dimostra questa codifica in azione più tardi oggi o domani. Per ora, sono curioso di vedere cosa pensano gli altri di questa codifica.


1
È possibile salvare bit sulle torri. Puoi determinare la parte della regina e quella del re in base alla posizione e non hai bisogno di sapere da quale parte provenga una torre. quindi hai solo bisogno di un po 'di informazioni sulla torre - spostate o immobili.
Non che Charles l'

... E in realtà, memorizzare quei dati a livello di pezzo è più facile da codificare / decodificare, ma se hai appena memorizzato un marcatore all'inizio, potresti salvare i bit nel peggiore dei casi (ad esempio, il marcatore 11001significa B'S MOVE W CAN KSC W CANT QSC B CANT KSC B CAN QSC). Sono 4 bit invece dei 5 bit per lato nella codifica o 3 bit per lato se si elimina il marcatore laterale sulle torri. ( KSC= Castello sul lato del re. QSC= Castello sul lato della regina )
Non che Charles l'

Inoltre, a causa delle promozioni, è possibile avere fino a 9 regine o 10 cavalieri (o qualsiasi altro pezzo non regale, non pedone)
Non che Charles

1

184 bit = 23 byte nel caso peggiore, e non troppo complicato:

A. Quali quadrati occupati: 64 bit = 8 byte B. Quali colori per i <= 32 quadrati occupati: 32 bit = 4 byte E ora usando solo i <= 30 quadrati occupati dai non re: B. usa PNBRQ codificato in radix 5, per 5 ^ 30 possibilità; e 32 * 31 * 2 * 4 * 4 * 9 per le posizioni di re, diritti di castellatura di colore bianco e nero, quadrato en passant (tra 8 possibilità più nessuna, una nona); questo numero 5 ^ 30 * 32 * 31 * 2 * 4 * 4 * 9 = 266075134277343750000000000 = 2 ^ 87.782 si adatta a 88 bit per un totale di 64 + 32 + 88 = 184 bit per l'intera codifica.

Questo può essere ridotto, ad es. 32 * 31 * 2 * 4 * 4 * 9 = 285696 può essere ridotto a 2 * (32 * 31 + 31 * 3 + 31 * 3 + 3 * 3) * 6 = 14244, usando fact al massimo 6 en passant candidate-candidate (incluso nessuno), e codificare i diritti di castling e le posizioni del re all'interno dello stesso set usando i fatti di castling contano solo quando il re nella casella iniziale. Ciò consente di risparmiare 4 bit.

Ho motivo di credere che non sia possibile raggiungere 18 byte, vale a dire il numero totale di posizioni di scacchi legali supera 2 ^ 144.

Il tuo schema a 160 bit è molto ingegnoso, ma penso che debba essere dato come programma di codifica / decodifica prima di esserne completamente sicuro.


1

Caso peggiore di 171 bit:

Ho combinato un paio di idee, così come alcuni dei miei pensieri.

Inizieremo con una scheda a 64 bit. Ogni bit rappresenta uno spazio occupato sul tabellone. Si riempiono lungo le file. Quindi l'inizio sembra:1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111

Ora, ogni pezzo sarà rappresentato da 4 bit. 1o bit: colore ( 0=white, 1=black) 2o-4o bit: uno di 8 tipi.

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

Alla fine includeremo un po 'che designa il turno. 0=white, 1=black.

4 bit * 32 pezzi = 128 bit e ho già 64 + 1 da turn e board. Questo dà un totale di 128 + 64 + 1 = 193 Non ho nemmeno iniziato con en passant o castling. Ben oltre il mio limite senza niente - nemmeno giri. È qui che iniziano i trucchi.

Okay - vedi quei tipi sopra? Bishop0 e Bishop1? Pedone0 e pedone1? Quei tipi sono così designati, perché ci dicono un po 'da inserire dopo questo pezzo. Quindi Bishop0 significa che dopo di esso ci sarà uno 0 - cioè che il prossimo pezzo sarà bianco. Bishop1 ci dice che il prossimo pezzo è nero, e il pedone0 e il pedone1 funzionano allo stesso modo. (Se questo pezzo è l'ultimo pezzo enumerato, allora ci parla invece del prossimo turno).

Il mio caso peggiore riguarda tutti i pezzi sul tabellone, quindi con 16 pedine e 4 vescovi, questo mi fa risparmiare 20 bit. Sono sceso a 173.

Va bene. Per un altro peggio nel mio caso peggiore - una volta che ci sono 16 di un colore codificato, smettiamo di codificare il colore - come sappiamo che va avanti. Il mio caso peggiore ora riguarda un pezzo bianco che arriva all'angolo più lontano senza catture. Lì, salvo solo un po '. 172.

Adesso cambierò l'ordine in cui nominerò i pezzi. Li nomineremo lungo le colonne iniziando dall'esterno che si sposta all'interno. La tavola nominata all'inizio rimarrà la stessa, ma quando posizionerò i pezzi su di essa, comincerò dai bianchi in basso a destra e salirò su quella colonna. Quindi salto in basso a destra in nero e salgo quella colonna. Salto nella cella sconosciuta in basso a destra bianca e così via - questo significa che il mio caso peggiore è di nuovo l'inizio. La mia ragione ha a che fare con il mio trucco en passant, i prossimi due pezzi che perdo e il castling.

Ora, per promuovere una pedina (come è stato discusso a lungo) un pezzo deve essere catturato. Pertanto, quando sappiamo che ci sono 32 pezzi, dobbiamo solo indicarne 31. L'ultimo pezzo è identificato in modo univoco. A quanto pare, per me, questo risparmia solo 2 bit - perché il mio ultimo pezzo potrebbe essere un pedone / vescovo (che normalmente mi costa 3 bit perché ne salvo uno sul pezzo successivo) il cui colore è già determinato e quindi era solo 2 bit. Sono sceso a 170 bit.

Quando i pedoni vengono promossi, cambiano semplicemente il loro tipo. Per ogni pezzo che esce dal tabellone mi libero di (minimo) 3 bit e due promozioni pedone mi costano 2 bit, quindi sto diminuendo (lentamente) nelle promozioni.

Arrocco. Perché avvenga il castellaggio, né il re né la torre rilevante potrebbero essersi mossi. Pertanto, quando una torre è in grado di arroccare sia essa che il re si troveranno nei loro luoghi originali. Quindi, le torri in grado di arroccare saranno elencate nello stesso posto dei re di quel colore. Poiché questo è illegale (due re o tre re dello stesso colore sulla lavagna) e può avvenire solo in tre possibili configurazioni per ciascun colore (a sinistra, a destra, entrambe le torri sono elencate come re) - la decodifica è assolutamente possibile. Quindi, per nessun bit abbiamo codificato il castling.

En Passant Qui utilizzeremo anche posizioni illegali. Solo una pedina può essere in pericolo di en passant alla volta. Deve essere nella sua quarta fila. Il pedone vulnerabile verrà "ribaltato" nella sua riga iniziale - scambiato con qualunque cosa ci sia. Dato che quel pedone è nella sua prima fila - una posizione illegale, la situazione sarà ovvia per il decodificatore - invertirà le posizioni e contrassegnerà il pedone come vulnerabile all'en passante.

Avevamo bisogno di confondere con l'ordine perché l'ultimo pezzo deve essere "identificato in modo univoco". In un ordine standard, non saremmo in grado di dire se il corvo nell'angolo posteriore potrebbe castello - questo non è noto. Quando lavoriamo dall'esterno, garantiamo che ovunque quella torre sia "elencata" sia nel suo angolo, o nel mezzo della scacchiera perché è stata scambiata con una pedina vulnerabile en passant, ci sarà un pezzo elencato dopo esso - così ci viene detto il tipo di torre. Sappiamo che ci sarà un pezzo dopo di esso perché, affinché un pedone sia vulnerabile, ci deve essere un pedone al suo interno (che sarà crucialmente codificato in seguito secondo le istruzioni sopra).

Oh, e per essere sicuri che il caso peggiore riguardi tutti i pezzi sulla scacchiera, una volta che abbiamo meno di 32 pezzi, possiamo usare la scheda a 64 bit per identificare il turno e le posizioni occupate usando gli 0 per rappresentare i pezzi quando i suoi bianchi girare e 1 quando è nero girare.

Quindi siamo diventati en passant e castling gratis. Abbiamo raccolto l'ultimo pezzo gratuitamente, sebbene ci sia voluto un po 'di finagling per renderlo piacevole con le regole en passant e castling. Abbiamo abbandonato 20 bit sui pezzi standard. Credo che il caso peggiore qui coinvolga una pedina bianca di mezzo colore spostata in avanti e un pezzo nero tra lui e la sua regina mentre tutti i pezzi sono sul tabellone. Doppio controllo rapido: il primo pezzo viene catturato - chiamalo un pedone, 3 bit fuori dal tabellone nel pedone, 3 bit sul tabellone nella forma di un ultimo pezzo, un bit nel marcatore del turno che scompare. Promuovi due pedine 2 bit sul tabellone. Ah dannazione, sono a 171.

EDIT Ho aggiunto il codice per un decodificatore (funzionante?) - in R - sotto. Ci vogliono i vettori di booleani come input - (scusate - non sono in grado di programmare bene tutto ciò che mi permetterebbe di usare effettivamente i bit) Ho anche incluso la posizione iniziale.

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

Questo codice crea 4 funzioni. Uno che fa una certa separazione di base dei pezzi e della struttura della tavola, oltre a capire il tipo di pezzo e tutti i pezzi "impliciti". La funzione successiva riempie la struttura della scheda con quei pezzi in un ordine leggermente bizzarro (e diverso dal mio algoritmo iniziale) [spiegato nei commenti di codice]. La prossima funzione prende la scheda riempita e rileva eventuali posizioni illegali - quindi le corregge e rinomina pedine vulnerabili all'en passant "x pawn-e" e qualsiasi torre che può "x rook-c". La funzione finale è un wrapper che esegue tali funzioni in ordine e fornisce un output che è la scheda corrente e il turno.

Ho anche incluso la codifica della posizione iniziale (anche se per vederlo dovrai chiamare c(startboard,newpieces)e il codice chiama la funzione wrapper in quella posizione.


Questo è interessante. Mi piacerebbe vedere un'implementazione funzionante come una prova del concetto.
Mego

L'implementazione di solito è a pochi passi oltre la dimostrazione del concetto, ma ho aggiunto un decodificatore. È in R e utilizza quindi i booleani anziché i bit (scusate, non volevo usare troppo tempo). Ma credo che dovrebbe essere una prova del concetto.
user5957401

0

229/226 bit

Questo risulta non avere molto successo, ma potrebbe salvare altre persone che seguono lo stesso percorso.

La versione semplice:

  • 1 po 'per chi è il turno
  • 4 punte per le quattro possibilità di castling
  • 3bit per le possibilità en passant . Questo ha più profondità che all'inizio ho capito. Il passante deve essere eseguito da una pedina che si sposta dallo stesso rango (riga) della pedina catturata. L'analisi dei casi indica che una volta che sappiamo quante pedine del colore che si sono spostate per l'ultima volta hanno avanzato esattamente due quadrati, ci saranno al massimo 6 casi en passant (incluso il caso in cui non vi siano pedine vulnerabili a en passant ). Il caso peggiore sono 5 pedine (potenzialmente tutte vulnerabili: ad es. PpPPpPPpHa cinque vulnerabili P). Con 6 pedine ci sono al massimo 2 pedine nemiche nello stesso rango, ognuna delle quali può minacciare al massimo 2 pedine en passant . Pertanto abbiamo bisogno di ceil(lg 6) = 3bit qui.

Quindi la tavola. La scheda ha 64 quadrati, quindi un indice quadrato può essere codificato in 6 bit. Elenchiamo gli uomini per rango, alternando i colori, iniziando dal re.

  • 6bit: posizione del re bianco. (Garantito di essere sul tabellone).
  • 6bit: posizione del re nero. (Garantito per essere sul tabellone. Nel peggiore dei casi in cui il re bianco è in un angolo, ci sono 60 possibili posti in cui potrebbe essere; nel migliore dei casi che il bianco non è su un bordo, ce ne sono 55).
  • 6bit: posizione della regina bianca. Se non esiste una regina bianca, ripeti la posizione del re bianco come segnale.
  • Per ogni regina bianca aggiuntiva, un 1po 'seguito da 6 bit per la posizione.
  • Un 0po
  • Idem per la regina nera.
  • Processo simile per torri, vescovi, cavalieri e pedine, sebbene possiamo saltare le pedine per un colore se abbiamo già rappresentato 16 uomini di quel colore.
  • Elimina il 0bit finale .

Questo costa alcuni 12bit per i re e 2*7*5-1 = 69bit per gli altri uomini. Nel peggiore dei casi, tutti e 32 gli uomini sono sul tabellone, 7per un uomo costa un po 'diverso dai re, per un totale di 12 + 7*30 - 1 = 221 bits. Quindi con i 8bit iniziali per lo stato globale abbiamo 229 bit .


La versione avanzata:

Usando la codifica aritmetica possiamo operare con lg num_possibilitiespiuttosto che ceil(lg num_possibilities)prendere solo uno ceilalla fine.

  • 1 po 'per chi è il turno
  • 4 punte per le quattro possibilità di castling
  • lg 6bit per le possibilità en passant .
  • 6 pezzi per il re bianco
  • lg 60 bit (nel peggiore dei casi) per il re nero
  • lg 63 pezzetti (perché non voglio complicarlo al livello di guardare i controlli) per la regina bianca, usando la posizione del re bianco se non ce n'è
  • Per ogni regina bianca addizionale, un 1po 'seguito da lg 62, lg 61, ecc bit per la sua posizione.
  • Un 0po
  • lg 63 pezzetti (o meno, se ci fossero regine bianche) per la regina nera.
  • eccetera.

L'ennesimo uomo che è effettivamente presente ha 66-npossibili valori. Se un tipo è assente per un colore, abbiamo speso 66-#men so farbit per registrarlo (più un bit per il separatore). I casi estremi sono:

  1. Tutti gli uomini presenti, incluso almeno un pedone non promosso da ogni parte. Spendiamo 5+lg 6sullo stato globale, 6+lg 60sui re, 29sui bit di separazione e SUM_{n=32}^{63} lg nsui bit in posizioni. Somma totale:ceil(225.82) bit. Deludente.
  2. Rimangono solo pedine non promosse. Spendiamo 5+lg 6sullo stato globale, 6+lg 60sui re, 29sui bit di separazione, 8*lg 63dicendo che non ci sono altri pezzi e SUM_{n=48}^{63} lg nsulle posizioni dei pedoni. Totale generale: ceil(188.94)bit. Meglio: salvando la seconda torre, il cavaliere e il vescovo per ogni parte che abbiamo fatto avanzare un po '.

Quindi il caso peggiore sembra essere di 226 bit , per un misero risparmio di 3.

Possiamo sicuramente fare meglio nel caso medio codificando i pedoni prima dei pezzi, dato che sono limitati a 48 quadrati anziché ai 64 interi. Tuttavia, nel peggiore dei casi, tutti gli uomini sono sul tavolo e tutti i pedoni sono stati promossi, penso questo finirebbe per costare 2 bit in più perché avremmo bisogno di una bandiera "senza pedine" piuttosto che essere in grado di contare gli uomini.


0

Questo è un argomento di discussione nei circoli degli scacchi.

Ecco una prova molto semplice con 164 bit https://groups.google.com/forum/#!topic/rec.games.chess.computer/vmvI0ePH2kI 155 è mostrato qui http://homepages.cwi.nl/~tromp /chess/chess.html

Strategia troppo semplificata:

  • Limitare i pedoni nel luogo in cui possono essere trovati i pedoni
  • Limita gli eserciti a considerare pezzi originali e possibili promozioni di pedine
  • Pensa intensamente alle promozioni e alle situazioni in cui le promozioni non sono possibili

2
Le risposte solo link non sono buone risposte. Dovresti fornire la risposta completa all'interno del tuo post, non solo alcuni link alla risposta. E se la tua risposta non è il tuo lavoro, probabilmente dovresti rendere il tuo post un wiki della community.
pastebin.com slash 0mr8spkT

La posta è originale. Aggiunta di dettagli per rispondere.
William Entriken,

1
Questo è un esempio del perché includi il contenuto nella tua risposta. Il secondo link è morto. È così? tromp.github.io/chess/chess.html
mbomb007

-2

Min: 0 bit

Max: 1734 243 bit (4.335 4.401 bit / scheda ammortizzata)

Previsto: 351 177 bit (4.376 4.430 bit / scheda ammortizzata)

Dal momento che posso determinare l'input e l'output che desidero, ho deciso di continuare con la codifica della storia del gioco fino a questo punto. Un vantaggio è che l'informazione aggiuntiva di chi è il turno è, en-passant, e chi ha la capacità di fortificare dove può essere derivato e non codificato.

Tentativo 1:

Ingenuamente ho pensato di poter codificare ogni mossa in 12 bit, 4 terzine del modulo (inizio x, inizio y, fine x, fine y) dove ognuno è 3 bit.

Assumiamo la posizione di partenza e spostiamo i pezzi da lì con il bianco che va per primo. Il tabellone è organizzato in modo tale che (0, 0) sia l'angolo in basso a sinistra del bianco.

Ad esempio il gioco:

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

Sarebbe codificato come:

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

Ciò porta a una codifica di 12 m bit in cui m è il numero di mosse effettuate

Da un lato questo potrebbe diventare davvero grande, dall'altro puoi considerare ogni mossa come il suo gioco, quindi ogni codifica codifica davvero m "scacchiere". Se lo hai ammortizzato, ottieni che ogni "scacchiera" è di 12 bit. Ma penso che questo sia un po 'barare ...

Tentativo 2:

Mi sono reso conto che ogni mossa nel tentativo precedente codifica molte mosse illegali. Quindi ho deciso di codificare solo le mosse legali. Enumeriamo le possibili mosse come segue, numerando ogni quadrato in modo tale che (0, 0) → 0, (1, 0) → 1, (x, y) → x + 8 y. Scorrere le tessere e controllare se c'è un pezzo e se può muoversi. In tal caso aggiungi le posizioni in cui può andare a un elenco. Scegli l'indice dell'elenco che è la mossa che vuoi fare. Aggiungi quel numero al totale corrente di mosse ponderato per 1 più il numero di mosse possibili.

Esempio come sopra: dalla posizione di partenza il primo pezzo che può spostarsi è il cavaliere nel quadrato 1, può spostarsi nel quadrato 16 o 18, quindi aggiungi quelli alla lista [(1,16),(1,18)]. Il prossimo è il cavaliere sul quadrato 6, aggiungi le sue mosse. Complessivamente otteniamo:

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

Poiché vogliamo la mossa (12, 28), la codifichiamo come 13 nella base 20 poiché ci sono 20 mosse possibili.

Quindi ora otteniamo il numero di gioco g 0 = 13

Quindi facciamo lo stesso per il nero, tranne per il fatto che numeriamo le tessere al contrario (per rendere più semplice, non necessario) ottenere l'elenco delle mosse:

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

Poiché vogliamo la mossa (11, 27), la codifichiamo come 11 nella base 20 poiché ci sono 20 mosse possibili.

Quindi ora otteniamo il numero di gioco g 1 = (11 ⋅ 20) + 13 = 233

Successivamente otteniamo il seguente elenco di mosse per il bianco:

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

Poiché vogliamo la mossa (6, 21), la codifichiamo come 13 nella base 29 poiché ci sono 29 mosse possibili.

Quindi ora otteniamo il numero di gioco g 2 = ((13 ⋅ 20) + 11) 20 + 13 = 5433

Quindi otteniamo il seguente elenco di mosse per il nero: [(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)]

Dal momento che vogliamo la mossa $ (10, 18) $ (10, 18)

Quindi ora otteniamo il numero di gioco g 3 = ((((19 ⋅ 29 + 13) 20) + 11) 20 + 13 = 225833

E continua questo processo per tutte le mosse rimanenti. Puoi pensare a g come alla funzione g (x, y, z) = x y + z. Quindi 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)

Per decodificare un numero di gioco g 0 , partiamo dalla posizione iniziale ed enumeriamo tutte le mosse possibili. Quindi calcoliamo g 1 = g 0 // l , m 0 = g 0 % l , dove l è il numero di mosse possibili, '//' è l'operatore di divisione intera e '%' è l'operatore del modulo. Dovrebbe contenere quel g 0 = g 1 + m 0 . Quindi eseguiamo lo spostamento m 0 e ripetiamo.

Dall'esempio sopra se g 0 = 225833 quindi g 1 = 225833 // 20 = 11291 e m 0 = 225833% 20 = 13. Avanti g 2 = 11291 // 20 = 564 e m 1 = 11291% 20 = 11. Quindi g 3 = 11291 // 20 = 564 e m 2 = 11291% 20 = 11. Pertanto g 4 = 564 // 29 = 19 e_m_ 3 = 564% 29 = 13. Infine g 5 = 19 // 29 = 0 e m 4 = 19% 29 = 19.

Quindi, quanti bit vengono utilizzati per codificare un gioco in questo modo?

Per semplicità, supponiamo che ci siano sempre 20 mosse per turno e per lo scenario peggiore scegliamo sempre la più grande, 19. Il numero che otterremo è 19 ⋅ 20 m

+ 19 ⋅ 20 m-1 + 19 ⋅ 20 m-2 + ⋯ + 19 ⋅ 20 + 19 = 20 m + 1 - 1 dove _m è il numero di mosse. Per codificare 20 m + 1 - 1 sono necessari circa i bit del log 2 (20 m + 1 ) che sono circa (m + 1) ∗ log 2 (20) = 4.3219 ∗ (m + 1)

In media m = 80 (40 mosse per giocatore), quindi occorrerebbero 351 bit per codificare. Se stessimo registrando molti giochi avremmo bisogno di una codifica universale poiché non sappiamo quanti bit saranno necessari per ogni numero

Peggior caso quando m = 400 (200 mosse per giocatore), quindi occorrerebbero 1734 bit per codificare.

Nota che la posizione che vogliamo codificare ci deve essere data tramite il percorso più breve per arrivarci seguendo le regole. Ad esempio, il gioco teorizzato qui non ha bisogno di m = 11741 per codificare la posizione finale. Invece eseguiamo una ricerca Breadth-First per trovare il percorso più breve verso quella posizione e codificarlo invece. Non so quanto dovremmo approfondire per enumerare tutte le posizioni degli scacchi, ma sospetto che 400 sia sopravvalutato.

Calcolo rapido:

Ci sono 12 pezzi unici o il quadrato può essere vuoto, quindi posizionarli su una scacchiera è 13 64 . Questa è una sovrastima enorme poiché include molte posizioni non valide. Quando siamo m ci muoviamo nel gioco abbiamo creato circa 20 m di posizioni. Quindi stiamo cercando quando 20 m = 13 64 . Registra entrambi i lati per ottenere il registro m = 64 * 20 (13) = 54.797. Ciò dimostra che dovremmo essere in grado di raggiungere qualsiasi posizione in 55 mosse.

Ora che ho calcolato il caso peggiore per essere m = 55 non m = 400, modificherò i miei risultati. Per codificare una posizione in cui m = 55 richiede 243 bit. Sto anche per dire che il caso medio è di circa m = 40 che richiede 177 bit per codificare.

Se utilizziamo l'argomento di ammortamento di prima, stiamo codificando 400 "scacchiere" in 1734 bit, in modo che ogni "scacchiera" occupi 4.335 bit nel peggiore dei casi.

Nota che g = 0 indica un gioco valido, quello in cui il pezzo sul quadrato più basso si sposta sul quadrato più basso che può.

Note aggiuntive:

Se vuoi fare riferimento a una posizione specifica nel gioco, potresti dover codificare l'indice. Questo può essere aggiunto manualmente, ad es. Concatenare l'indice al gioco o aggiungere una mossa "fine" aggiuntiva come ultima mossa possibile in ogni turno. Questo ora può rendere conto dei giocatori che hanno concesso, o 2 di fila per indicare che i giocatori hanno accettato un pareggio. Ciò è necessario solo se il gioco non è terminato in uno scacco matto o in una situazione di stallo in base alla posizione, in questo caso è implicito. In questo caso porta il numero di bit necessari in media a 356 e nel peggiore dei casi 1762.


1
Il tuo argomento di "ammortamento" non funziona. L'obiettivo è quello di codificare una scheda fornita dall'utente. Non puoi dividere il costo della codifica di questa scheda tra le 400 schede ausiliarie che potresti generare lungo il percorso. (Ciò andrebbe bene solo se quelle 400 schede fossero state scelte indipendentemente dall'utente e non vincolate dall'obbligo di formare una partita a scacchi.) Inoltre, una partita a scacchi può teoricamente fare molte migliaia di mosse e l'OP è chiaro di essere interessato al caso peggiore.
Anders Kaseorg,

@AndersKaseorg: Very true. Dipende davvero dall'obiettivo. Se stai provando a memorizzare un intero gioco con tutti gli altri algoritmi, ci vorranno m * c byte dove m è il numero di mosse e c è la dimensione del loro output. Quindi, se stai provando a memorizzare un intero gioco a 80 mosse usando la soluzione a 160 bit ci vorrebbero 12800 bit mentre il mio ne prenderebbe solo 351. Per il bene della concorrenza, ammetto che hai ragione, ma ho pensato che fosse una bella proprietà sottolineare dal momento che è molto comune voler memorizzare interi giochi e non solo schede.
edggy,

L'obiettivo è inequivocabile. “L'obiettivo è quello di creare la più piccola rappresentazione di una scacchiera che possa essere usata (una volta decodificata) per determinare tutte le possibilità di movimento per un giocatore in quel turno. ... Il tuo punteggio è determinato nel peggiore dei casi - massima dimensione possibile in bit. "
Anders Kaseorg,

@AndersKaseorg: non ho mai sostenuto che fosse ambiguo. Ho appena deciso di adottare un approccio diverso. Una cosa da notare è che per trovare la scheda più piccola usando il mio algoritmo ho bisogno del percorso più piccolo per arrivare a questa posizione. Ad esempio nel gioco del turno 11741 che hai collegato per raggiungere la stessa posizione sul tabellone non ho bisogno di seguire quel percorso se tutto ciò che ci interessa è il tabellone. Quindi, al fine di codificare il gioco collegato, trovo solo il gioco più corto che rimane con 2 re su quei quadrati che possono essere solo 200 turni o meno. Questo può essere fatto con una ricerca approfondita.
edggy,

Usare un gioco equivalente più breve va bene, se puoi effettivamente dimostrare che ogni posizione è raggiungibile in 200 turni o meno (in questo momento sembra solo un'ipotesi). Dovrai anche tenere conto delle posizioni degli scacchi con più di 100 mosse legali , a meno che tu non possa provare che non sorgono all'interno della tua costruzione. Dividere il risultato per il numero di mosse nel gioco non è ancora consentito dalle regole di questa sfida.
Anders Kaseorg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.