Kompresi papan catur terkecil


39

Tulis algoritma atau program yang dapat menyandikan dan mendekode papan catur. Tujuannya adalah untuk membuat representasi terkecil dari papan catur yang dapat digunakan (setelah diterjemahkan) untuk menentukan semua kemungkinan pergerakan pemain pada giliran itu.

Pengkodean harus dapat menunjukkan:

  • Giliran siapa itu.
  • Apakah pemain dapat melakukan kastil di setiap sisi.
  • Apakah pemain dapat melakukan en-passant, dan jika demikian, mana dari pion mereka?
  • Posisi semua bagian.

Catatan penting tentang kastil: Jika putih menggerakkan raja mereka satu putaran, dan kemudian memindahkannya kembali berikutnya, harus jelas bahwa mereka tidak dapat kastil di kedua sisi setelah itu. Hal yang sama akan terjadi jika mereka memindahkan benteng kiri atau kanan mereka. Meskipun papan secara visual dalam keadaan yang sama seperti dua belokan yang lalu, kondisi permainan telah berubah. Info lebih lanjut di sini: http://en.wikipedia.org/wiki/Chess#Castling

Catatan penting pada en-passant: Ini juga merupakan langkah yang peka terhadap belokan. Baca aturan untuk info lebih lanjut. http://en.wikipedia.org/wiki/Chess#En_passant

Tentukan input dan output sesuai kebutuhan. Alat peraga utama bagi siapa pun yang paling bisa mengompresnya!

Skor Anda ditentukan skenario terburuk - ukuran maksimum yang mungkin dalam bit. Pastikan Anda menunjukkan bagaimana Anda menghitungnya nomor itu dan apa yang Anda perhitungkan. Tembak untuk kasus terburuk terkecil!


Apa yang Anda maksud dengan "bitwise"?
Peter Taylor

Apakah kode ini terkecil atau paling terkompresi? Kebanyakan terkompresi lebih menarik.
Justin

Maaf karena tidak menjelaskan. Bitwise dalam arti bahwa Anda hanya dapat mengompresnya jika Anda mulai menyatakannya sebagai bit, yang akan membutuhkan beberapa operasi bitwise. Penggunaan yang buruk pada bagian saya. Juga kode terkompresi, bukan terkecil.
Seltzer

2
@ GeekWithALife Ya, mungkin saja ada 18 ratu di papan tulis pada saat bersamaan. Ikuti tautan ini dan klik tombol playback untuk contoh.
oqueifrage pelit

1
@ AJMansfield, itu mungkin berguna untuk papan dengan sekitar 28 orang, tapi saya menghitung bahwa 117 bit lebih banyak untuk papan dengan semua 32 orang, yaitu sekitar 50 bit kurang dari target. Masalahnya adalah begitu Anda pergi di bawah 32 pria, promosi dapat memberi pemain lebih banyak uskup.
Peter Taylor

Jawaban:


27

Min: 12 bit
Maks:
Rata-rata:

Pernah dan berpikir semalam bahwa saya mungkin bisa membuatnya lebih kecil.

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)

Hasilnya adalah ukuran 12 bit yang mengesankan !

Jadi bagaimana dengan K +1 jenis karya lainnya?

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

Ada 2 kemungkinan pengaturan sub tree.

   /\      /\
  +  K    K  +

Keduanya menghasilkan ukuran bit yang sama untuk semua bagian. Jadi tidak ada bedanya dengan yang kami gunakan, saya akan memilih yang pertama.

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

Jadi pada Raja +2 jenis potongan lainnya

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

Ada 5 kemungkinan sub pohon (saya akan menggunakan 1 dan 2 untuk menunjukkan yang mana dari potongan-potongan itu.)

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

Jadi kita akan membutuhkan 3 bit untuk mengkodekan sub pohon mana yang akan digunakan.

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

Masih melakukan analisis untuk lebih banyak potongan

+3 Lainnya

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

+4 Lainnya

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

+5 Lainnya

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

Maks: 208?


Apakah mungkin untuk menyandikan semua sub-pohon ini menjadi 9 bit?

Jika kami totalkan semua sub-pohon yang memungkinkan, kami mendapatkan 392 sub-pohon yang memungkinkan.

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

Menggunakan ID Freq

Karena ada 164603 frekuensi potongan unik .

Log2( 164603) = 17.3286110452
             ~ 18 bits

0
 0000 0000 0000 0000 00  Freq ID

(+000) (+00) Castling

Maks: = 204 bit


rev 3

Min: 82 Maks: 199 Rata-rata: 160

Akhirnya sempat melakukan beberapa analisis untuk menemukan ukuran bit maksimum. Dengan pengodean huffman yang optimal untuk masing-masing frekuensi potongan unik .

               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 

Perhatikan ini adalah ukuran terburuk yang mungkin, yang kolom En-Passant menggigit jika jumlah pion lebih besar dari satu. Terlepas dari warna-warna pion dan posisi ada potensi untuk beberapa papan menjadi 3 bit lebih kecil.

Juga hanya ada 144 ukuran berbeda (kasus terburuk) untuk ukuran papan.


75 - 216 bit (v2) v1 Ukuran minimum adalah 98 bit (12,25 byte), hanya dua raja di papan tulis.

Ukuran maksimum hanya 216 bit (27 byte.) Dalam tidak suka: -

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

Rata-rata ukurannya sekitar 157 bit (19,625 byte).

Potongan

Untuk menyandikan papan, saya menggunakan skema penyandian pohon biner. Kotak kosong adalah yang paling sering dari mana saja antara 32 dan 62 penampilan. Berikutnya adalah bidak, kemudian Benteng, Ksatria, Uskup dan yang paling jarang adalah Ratu dan Raja.

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

Papan awal dapat dikodekan hanya dalam 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

Untuk menunjukkan siapa yang pindah hanya perlu satu bit

0-> Black , 1-> White

Castling dapat dikodekan dalam 4 bit.

 B  W
LR LR
00 00

Jadi saya sudah menggunakan 171 bit (21,375 byte)

En-Passe dapat dikodekan menjadi hanya 16 bit (2 byte)

Jadi totalnya 187 bit (23,375 byte).

Tata letak

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

Belum menulis kode apa pun.

Perhatikan bahwa 3 bit yang tidak digunakan. Jadi maksnya adalah 213bits .


Kemungkinan Perbaikan

1) Mengurangi bentuk blok header 24 hingga 8 bit (dengan saran @Peter Taylor)

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

2) Header panjang variabel

Header kecil 4 bit yang diperbaiki

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

Blok bit tambahan berikutnya (Jika castling masih memungkinkan)

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

Blok bit tambahan berikutnya (jika ada pion)

000--> En-Passant column Position

Jadi sekarang saya memiliki header panjang variabel 4 - 11 bit


3) Gunakan skema penyandian yang berbeda tergantung pada bagian yang tersisa di papan tulis.

Dengan mengubah pengkodean pohon tergantung pada potongan apa yang ada di papan dan ada frekuensi.

Satu kemungkinan penyandian untuk kondisi akhir game (No Pawns)

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

Yaitu sekitar ~ 4 bit per potong.

Jenis potongan apa yang ada di papan tulis?

RBNQK Permutation
11111 (11111)

Permutasi adalah Panjang variabel 0-5 bit. Jika hanya satu jenis potongan yang tersisa maka jangan memasukkannya.

Permutasi potongan mana yang digunakan untuk pohon? Ini adalah faktorial dari jumlah potongan dalam contoh di atas itu adalah 5 buah sehingga 120 kemungkinan permutasi yang dapat dikodekan.

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

Ingat bahwa ada bit tambahan untuk kotak dan warna kosong.


Contohnya

Mari kita beri contoh hanya QK yang tersisa

RBNKQ
00011

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

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

0000 00011 Header ==> 9 bits

Total 81 bit


Mari kita beri dan contoh hanya raja yang tersisa

 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

Satukan semuanya

 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

Jadi saya menghitung encoding terkecil untuk papan di 75bits (9 bit 3 bit)

Masih belum menghitung bagaimana skema pengkodean ini memengaruhi ukuran maksimum.


Perbaikan 4

Kurangi jumlah bit untuk castling menjadi hanya 2 bit. Hanya castling untuk pemain yang giliran itu.

 0 Castling possible (from header block)
 LR 
 00

Kalau dipikir-pikir, mungkin lebih baik memasukkan 2 bit ke dalam blok header.


Anda tidak perlu 16 bit untuk melintas. Paling banyak satu pion pindah giliran terakhir, jadi empat bit sudah cukup (misalnya 1111untuk "tidak boleh lewat" atau kolom sebagai nomor biner sebaliknya).
Peter Taylor

Mengapa pion mendapatkan posisi yang lebih baik di pohon? Dalam kasus umum mereka paling umum, tetapi dalam kasus ekstrim R / B / N dapat muncul 10 kali.
ugoren

@ PeterTaylor, sebenarnya 3 bit sudah cukup untuk orang yang lewat. Jika Anda hanya menghitung kolom dengan pion peringkat 5 hitam (dengan asumsi langkah putih), 8 menjadi tidak valid.
ugoren

1
Perhatikan bahwa kasus terburuk Anda sebenarnya tidak mungkin. Promosi tidak mungkin dilakukan tanpa tangkapan (setidaknya diperlukan satu tangkapan per 2 promosi).
ugoren

2
Catatan untuk mengkodekan 64 posisi (untuk raja putih atau hitam) Anda memerlukan 6 bit (2 ** 6 = 64).
lambruscoAcido

17

192 bit (kasus terburuk)

Berikut adalah skema penyimpanan yang sangat sederhana yang harus mengatasi promosi gadai yang sewenang-wenang, dan tidak pernah membutuhkan lebih dari 64 + 4 × 32 = 192 bit:

  • 64 bit pertama menyimpan bitboard yang memberi tahu di mana keping-keping itu (tetapi tidak apa adanya). Yaitu, kami menyimpan satu bit untuk setiap kuadrat papan catur (mulai dari kuadrat a1, kemudian b1, c1, dll. Hingga kuadrat h8) sedemikian rupa sehingga kuadrat kosong diwakili oleh 0 dan kuadrat terisi oleh 1.

  • Selanjutnya, untuk masing-masing kotak yang ditandai ditempati di papan bit, kami menyimpan 4-bit nibble yang menyandikan potongan di kotak itu. Yang pertama dari empat bit mengkodekan warna potongan (0 = putih, 1 = hitam), sedangkan tiga bit sisanya mengkodekan jenis potongan:

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

    Jenis potongan

    0 = (normal) gadai
    1 = (normal) benteng
    2 = ksatria
    3 = uskup
    4 = ratu
    5 = raja (pemain bergerak selanjutnya)
    6 = raja (pemain lain)

    Perhatikan dua penyandian untuk raja, yang digunakan untuk menentukan giliran pemain mana yang akan dipindahkan. (Faktanya, karena selalu ada dua raja di papan tulis, memungkinkan untuk empat kombinasi kode 5 dan 6, kita dapat dengan mudah menyandikan sedikit informasi kedua di sini.)

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

    Untuk menyandikan informasi tambahan yang diperlukan untuk aturan en castant dan castling, kami memperkenalkan satu jenis keping tambahan, yang menunjukkan pion atau benteng tergantung pada baris yang muncul pada:

    7 (pada baris 1 dan 8) = benteng yang tidak pernah bergerak, dan rajanya juga tidak pernah bergerak, dan yang karenanya memenuhi syarat untuk casting
    7 (pada baris 4 dan 5) = pion yang baru saja maju dua kotak, dan Oleh karena itu dapat ditangkap saat lewat

Menyatukan semuanya:

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

Total jumlah bit yang diperlukan untuk mengkodekan keadaan papan adalah 64 + 4 × # dari potongan-potongan di papan. Karena tidak akan pernah ada lebih dari 32 buah di papan tulis, panjang maksimum penyandian ini adalah 192 bit.

Misalnya, menggunakan pengkodean yang dijelaskan di atas, keadaan awal papan akan dikodekan sebagai (spasi kosong dimasukkan untuk dibaca):

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

atau, dalam heksadesimal:

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

2
"pion yang baru saja maju dua kotak" dan "benteng yang tidak pernah bergerak" bisa berbagi slot negara yang sama karena mereka saling eksklusif tergantung pada baris mereka berada. Status bebas ekstra dapat digunakan untuk menyandikan "raja warna yang gilirannya"; Anda harus bisa menyingkirkan bit yang menggantung seperti itu.
FireFly

Anda juga bisa menyimpan sedikit dengan hanya menyimpan 63 bit untuk bitboard, dan menyimpulkan bit terakhir dari jumlah orang yang dikodekan. (Tidak jelas bagi saya apakah ini curang atau tidak, karena ini memerlukan pengkodean eksternal dari panjang urutan bit). Dan jika Anda membuang status 6 dan 7 untuk pria, Anda harus menyandikan hingga 6 ^ 32, yang membutuhkan 82,7 bit; pembulatan hingga 83 ini menghemat 13 bit menggunakan status 6 dan 7, dan Anda dapat menyandikan informasi yang sama hanya dalam 8 bit.
Peter Taylor

Terima kasih, @ Kebakaran! Saya sudah menerapkan saran Anda. (Saran Peter Taylor bahkan lebih efisien, tentu saja, tetapi saya belum menggunakannya sejauh ini karena saya agak menyukai penyandian biner sederhana dari skema saat ini. Anda selalu dapat mengirimkannya sebagai entri terpisah ...)
Ilmari Karonen

Oke - ini agak rumit. Tapi dengarkan aku. Jika Anda hanya mengambil 1 bit hit pada indikator belok, Anda bisa mengganti raja dengan belokan dengan potongan yang saya sebut pawn1. Ubah gadai menjadi gadai0. Sekarang, setiap kali ada gadai (tidak rentan melintas) - Anda juga mendapatkan sedikit informasi pada bagian berikutnya (baik 0 untuk pion0 atau 1 untuk pion1). Karena ada 16 pion, Anda mendapatkan 16 bit kurang 1 untuk indikator belokan. Setiap kali ada pion yang rentan terhadap pelintas, Anda harus menambahkan satu bit kembali setelahnya. Tetapi karena en passant harus terjadi segera, keuntungan minimum Anda adalah 14 bit.
user5957401

Anda juga bisa melakukan hal serupa dengan sesuatu seperti uskup. Misalkan Anda memiliki uskup yang tidak berada dalam 'zona khusus' (10 titik di sudut-sudutnya dan barisan tengah di sisinya) ditandai sebagai istimewa. Karena Anda tahu lokasinya - Anda tahu itu adalah seorang uskup. Sekarang Anda memiliki dua uskup dan dapat memberi mereka masing-masing 0 atau 1 di bagian berikutnya. Ini memberikan hingga 4 bit - tetapi kasus terburuk memiliki uskup di seluruh zona khusus, dan tidak ada keuntungan.
user5957401

14

Kasus terburuk 160 bit

Setelah memposting jawaban saya sebelumnya 22 byte, saya mulai bertanya-tanya apakah kita bisa turun ke 21 byte. Namun ketika saya melihat 166 byte Peter Taylor yang luar biasa saya pikir, "Tunggu, sepertinya lima kata 32-bit bisa dibuat!"

Jadi setelah cukup banyak berpikir, saya datang dengan ini: 159.91936391 bytes (cocok cukup ketat!) Tingkat kompresi ini akan memerlukan program yang cukup rumit tetapi saya telah memikirkan bagaimana membuatnya berjalan dalam waktu yang wajar.

Ini akan menjadi posting yang panjang, jadi tolong bersabar, saya akan memposting apa yang saya bisa hari ini dan menambahkan beberapa bit kode segera.

Jadi, inilah cara melakukannya:

En Passant and castling dikodekan oleh posisi ilegal (0 bit)

Sambil lalu

Seperti disebutkan dalam jawaban lain, ada maksimal 5 kotak yang memungkinkan pion rentan terhadap en passant dapat berdiri. Ini adalah kotak di sebelah pion pemain yang gilirannya.

Untuk menyandikan ini, pion yang rentan terhadap en passant dipertukarkan dengan apa pun yang ada di salah satu kotak di baris pertama atau terakhir. Ini bisa berupa laki-laki atau kotak kosong. Ini menghasilkan posisi ilegal, karena pion tidak dapat berada di baris ini. Decoder harus mengembalikan pion ke posisi yang benar, mengekstraksi informasi yang lewat.

Agar hal ini tidak mengganggu pengkodean castling, penting bahwa kotak-kotak di mana raja berdiri pada awal permainan tidak terganggu, dan bahwa prosedur enkode en passant tidak menempatkan raja di samping satu sama lain, yang akan menjadi posisi raja ilegal. Untuk memenuhi poin kedua, pembuat enkode memiliki dua pilihan kuadrat mana yang dipertukarkan dengan pion en passant. Kuadrat pilihan pertama untuk masing-masing hingga 5 pion adalah A8, B8, C8, G8, H8. Pilihan kedua: A1, B1, C1, G1, H1.

Castling

Seorang raja yang diizinkan untuk kastil menurut definisi, masih di alun-alun awal. Dengan raja putih di alun-alun awal, ada total 63 kotak di mana raja hitam bisa berdiri, 58 di antaranya legal (dia tidak diizinkan untuk bergerak tepat di sebelah raja putih karena dia akan menempatkan dirinya dalam kendali.) Jika raja kulit putih diizinkan untuk benteng, ia juga diizinkan untuk benteng dengan benteng kirinya, benteng kanannya, atau keduanya. Dengan demikian ada 3x58 = 174 kemungkinan di mana raja putih dapat kastil, 174 lainnya di mana raja hitam dapat kastil, dan 3x3 = 9 lebih lanjut di mana keduanya dapat kastil, total 357.

Ada 420 pengaturan ilegal dari dua raja di mana mereka berada di kotak yang berdekatan: 3x4 = 12 ketika raja putih di sudut, 5x24 = 120 ketika dia berada di tepi, dan 8x36 = 288 ketika dia berada di alun-alun lainnya. Oleh karena itu ada posisi ilegal yang cukup mudah untuk menyandikan semua kemungkinan kemungkinan castling.

Jika setidaknya satu raja diizinkan untuk kastil, pembuat enkode akan mencari data kastil dan data posisi raja-raja yang tidak diizinkan untuk kastil dalam sebuah tabel (atau sebagai alternatif, gunakan algoritma yang tidak akan saya sebutkan di sini) dan menghasilkan ilegal posisi kedua raja. Kemudian akan bertukar raja dengan apa pun yang terjadi pada kotak ini.

Adalah penting bahwa ini dikodekan setelah dan diterjemahkan sebelum en passant, jika tidak ada beberapa gangguan potensial.

Perbandingan

Jadi, sejauh ini saya tidak menggunakan bit! Melihat jawaban Peter, saya masih memiliki yang berikut untuk dikodekan:

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

Ini untuk kasus terburuk dari 29 pria (lihat jawaban Peter.) Di bawah ini saya akan menunjukkan bagaimana saya membuat perbaikan kecil (setidaknya untuk kasus 29 pria) pada kedua poin yang ditandai **.

Kotak mana yang ditempati / giliran siapa?

Cara mudah untuk menyandikan kotak mana yang ditempati adalah dengan kotak 64 bit. Ini juga memberi tahu kami berapa banyak kotak yang ditempati. Namun agak boros karena tidak mungkin ada lebih dari 32 kotak. Solusi saya adalah dengan menggunakan 1 untuk mengkodekan untuk kotak yang ditempati ketika giliran Putih dan 0 untuk mengkodekan untuk kotak yang ditempati saat giliran Hitam. Sekarang semua kombinasi digunakan dan tidak ada limbah.

Jadi kita menghemat sedikit untuk menyimpan belokan: kurang dari 32 1, giliran putih, lebih dari 32 1, giliran hitam. Satu-satunya kasus ambigu adalah ketika semua pria di papan tulis dan ada 32 1 dan 32 0. Karenanya diperlukan bit ekstra untuk kasus ini saja. Karena tidak ada promosi sampai penangkapan terjadi, bit tambahan ini tidak mempengaruhi kasus terburuk secara keseluruhan (yang terjadi dengan 3 orang ditangkap dan 29 sisanya.)

Warna laki-laki yang menempati kotak

Kita tahu dari atas berapa banyak pria di sana. Ekstrak segitiga Pascal berikut menceritakan berapa banyak kemungkinan yang ada untuk distribusi hitam dan putih yang berbeda. Misalnya, untuk 3 pria, kemungkinannya adalah: 3 pria hitam (1 permutasi) 2 hitam, 1 putih, (3 permutasi), 1 hitam, 2 putih (3 permutasi), 3 putih (1 permutasi). Totalnya adalah 2 3 = 8. Secara umum, untuk jumlah pria yang lebih rendah ada 2 n kemungkinan. Namun semua kemungkinan hitam dan semua putih adalah ilegal (setidaknya raja dari masing-masing pihak harus di papan tulis) sehingga jumlah permutasi hukum yang sebenarnya adalah 2 n -2 (abaikan angka 1 pada segitiga Pascals.)

Untuk lebih dari 16 pria total, ada kendala tambahan yaitu tidak boleh ada lebih dari 16 pria dari setiap warna di papan tulis. Oleh karena itu ketika semua 32 pria di papan harus ada 16 dari masing-masing dan total kemungkinan jumlah adalah 601.080.390 yang cukup sedikit kurang dari 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

Jumlah kemungkinan dapat ditemukan dengan menjumlahkan "baris" dari ekstrak segitiga pascals ini (yang saya maksud adalah diagonal NE-SW dari tabel, karena saya memutar segitiga 45 derajat berlawanan arah jarum jam untuk presentasi yang nyaman. Jumlah bit yang dibutuhkan Oleh karena itu untuk menyandikan belokan, kuadrat yang ditempati dan warna pria adalah sebagai berikut:

Hingga 25 pria: sedikit kurang dari 64+ (jumlah pria)
Untuk lebih dari 25 pria:

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

Untuk dua warna, pria mana dan dalam urutan apa?

Seperti jawaban sebelumnya, tidak ada pion yang dapat dipromosikan sampai penangkapan terjadi, karena setiap pion diblokir oleh pion dengan warna yang berlawanan pada kolom yang sama. Jawaban Peter menganggap (sebagai batas atas) bahwa setiap tangkapan dapat menyebabkan satu promosi untuk pihak yang ditangkap dan dua untuk pihak yang ditangkap. Namun kami dapat membagi ini menjadi beberapa kasus:

  1. Pion hitam menangkap pion putih: Sekarang pion yang menangkap bebas untuk dipromosikan karena ia sekarang berada di kolom yang berbeda. Rekannya di kolom yang sama juga bisa mempromosikan. Pion hitam di kolom asli pion putih juga bisa mempromosikan. Ini adalah satu-satunya kasus yang mengizinkan 3 promosi.

  2. Pion hitam melewati pion putih di kolom yang berdekatan dan kemudian menangkap potongan putih (selain pion) di belakang. Ini memungkinkan pegadaian menangkap dan pion putih yang ada di kolom asli untuk mempromosikan. Satu promosi untuk setiap sisi.

  3. Pion putih ditangkap oleh potongan (selain pion.) Ini biasanya memungkinkan satu promosi untuk Black saja. Satu-satunya pengecualian adalah ketika itu membebaskan formasi gadai yang diblokir yang sudah disebabkan oleh beberapa menangkap pion bergerak ke kolom yang sama.

Jadi, sebagai kasus dasar, kita dapat mempertimbangkan bahwa setiap tangkapan memungkinkan satu promosi masing-masing untuk kedua belah pihak. Dalam hal pria yang ditangkap adalah bidak, mungkin ada promosi tambahan untuk pihak yang menangkap.

Saya telah menulis sebuah program yang mirip dengan Peter. Ini agak kasar, tetapi memiliki tambahan penting: ia dapat menghitung jumlah permutasi yang mungkin ketika seorang pemain mulai dengan kurang dari 8 pion normal. Berikut adalah beberapa data yang dihasilkan oleh program:

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

Kita dapat melihat bahwa untuk kasus seperti 8 pion, 15 pria, 0 promosi, jumlah permutasi hanya sedikit kurang dari untuk 8 pion 16 pria, 0 promosi. Namun jika kita mempertimbangkan kasus seperti 7 pion, 15 pria, 0 promosi (yang sama dengan mempertimbangkan bahwa pria yang ditangkap jelas merupakan pion), kita mendapatkan sekitar setengah jumlah permutasi.

Jadi, Untuk kasus ketika Black memiliki 16 pria dan putih memiliki 15 pria, kita dapat mempertimbangkan perkiraan batas atas 2 promosi untuk Black dan satu promosi untuk White:

5383778400 x 660810150 = 3.55766E+18 possibilities

Namun kami dapat melakukan yang lebih baik jika kami melanjutkan sebagai berikut.

A. Pertimbangkan satu promosi masing-masing untuk Hitam dan Putih dengan asumsi bahwa pria Putih telah kehilangan bisa dari jenis apa pun:

843242400 x 660810150 = 5.57223E+17 possibilities

B. Pertimbangkan kemungkinan tambahan untuk Black jika dia memiliki dua promosi, dikalikan hanya dengan kemungkinan untuk White di mana dia kehilangan pion.

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

Menambahkan dua ini bersama-sama kita dapatkan 2.25072E + 18, yang merupakan jumlah yang lebih kecil dari 3.55766E + 18. Semua kemungkinan hingga 3 tangkapan (29 orang tersisa) tercantum di bawah ini.

(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

Jadi untuk kasus terburuk dari satu sisi dengan 15 pria dan yang lainnya dengan 14 pria, kita membutuhkan 67,804 bit.

Menambahkan ini ke 92,116 bit yang diperlukan untuk menentukan kotak dan warna mana, kami mendapatkan total 67,804 + 92,116 = 159,92 bit.


1
Banyak terima kasih kepada @Einacio karena mengubah koma desimal saya ke poin desimal. Saya melakukan banyak tabel di Excel di komputer Spanyol, dan memposting ini adalah pekerjaan besar, jadi memperbaiki ini adalah sesuatu yang saya tinggalkan untuk nanti. Seperti yang saya katakan, saya belum menyelesaikan posting ini, saya akan menambahkan program penghitungan permutasi saya dan beberapa fragmen kode tentang encoding / decoding ketika saya punya waktu. PS. Saya tidak tahu begitu banyak orang membaca ini :-)
Level River St

pada akhirnya Anda berhasil mengambil byte alih-alih bit yang merupakan hal yang Anda maksudkan, yang mungkin menyebabkan beberapa cinfusion ke pembaca
masterX244

13

Kasus terburuk 177 bit

Algoritme ini, walaupun hampir tidak sederhana, memberikan 177 bit kasus terburuk (184b = 23B dalam praktiknya), 13b (16b = 2B) skenario kasus terbaik ketika hanya ada 2 raja yang tersisa.

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

Sangat bagus. Anda dapat menjadikan ini lebih efisien dengan mengganti bit 14-105 (92 bit) dengan pengkodean berdasarkan koefisien multinomial. sum_{i=0}^{15} sum_{j=0}^{15} 62! / (i! j! (62-i-j)!) < 2^87.45.
Peter Taylor

Satu-satunya hal yang akan saya ubah adalah membuat versi yang lebih disederhanakan untuk area enpassant. Sebagai contoh: jika Anda menyandikan 30 buah di basis 5, dan ada maksimum 5 posisi enpassan, maka Anda dapat memiliki 5 ^ 31 <2 ^ 72. Sama seperti jika Anda membaginya dalam enpassant (13) dan non-enpassant (59), tetapi tanpa kompleksitas tambahan.
Alin Stoian

Melakukan itu sebenarnya akan menggunakan 1 bit ekstra. Alasannya adalah bahwa ada (kemungkinan terburuk) ada 5 kemungkinan penting, tetapi saya masih perlu menyatakan kemungkinan untuk "tidak berkuasa", yaitu negara ke-6. Bit 1 tambahan akan dalam hal ini pergi ke mendeklarasikan mungkin atau tidak (dan dengan pendekatan ini saya juga bisa menggunakan pendekatan yang lebih sederhana dengan pengkodean 30 buah melewatkan blok enpassant, dan menggunakan 3 bit secara terpisah untuk cek enpassant, yang akan juga mengarah ke penggunaan +1 bit). Baris ke-5 berikut akan memungkinkan 5 enpassan potensial (giliran White): BWBBWBBW
FIQ

ya kau benar.
Alin Stoian

7

166 bit

  • 1 bit: giliran siapa itu?
  • 2bits: opsi castling mana yang terbuka? (NB saat membaca pertanyaan dengan saksama, Anda hanya perlu merekam opsi castling untuk pemain yang mendapat giliran).
  • lg 6 ~= 2.585bits: opsi en passant mana yang terbuka? (Lihat jawaban saya yang lain)
  • lg sum_{i=1}^{16} sum_{j=1}^{16} 64! / (i! j! (64-i-j)! = lg 3629590441720924477681996172 ~= 91.552 bits: kotak mana yang ditempati oleh pria dengan warna apa?
  • Paling buruk lg 451366131803622235200 ~= 68.613menunjukkan pria mana dan urutannya (lihat di bawah)

Menggunakan pengkodean aritmatika (karena pada setiap langkah kami menerapkan distribusi seragam) kami dapat mencapai ceil(3 + 2.585 + 91.552 + 68.613) = 166bit.

Pengkodean untuk laki-laki: mengingat bahwa kita tahu berapa banyak laki-laki dengan warna tertentu, kita dapat dengan mudah menyebutkan semua kemungkinan distribusi / multiset pria (mis. Dengan 5 orang kita mungkin memiliki satu Raja, satu Ratu, dua Benteng, dan sebuah Pion) dan kemudian kita dapat mempertimbangkan semua permutasi yang mungkin dari setiap distribusi.

Namun, kami dapat melakukan lebih baik lagi dengan mempertimbangkan saling ketergantungan akun. Saya hanya melakukan ini pada tingkat yang sangat dasar: berapa banyak promosi yang memungkinkan? Gadai hanya bisa menjadi "berlalu" dan mampu mempromosikan dalam tiga cara: ia menangkap dan bergerak ke kolom yang berbeda; atau pion lawannya menangkap dan bergerak ke kolom yang berbeda; atau pion lawannya ditangkap. Dengan demikian penangkapan untuk putih berpotensi menciptakan dua bidak yang berlalu untuk putih dan satu untuk hitam.

Kami dapat membangun sebagian tabel batas atas pada promosi:

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

Kami juga dapat menghitung jumlah permutasi mengingat pemain memiliki pemain Ndan tidak lebih dari Ppion yang dipromosikan:

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

Menggabungkan keduanya, kita bisa mendapatkan jumlah bit yang diperlukan untuk menentukan kedua permutasi mengingat jumlah pria di kedua sisi:

           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

Jika tidak ada di bagian tabel ini, kita dapat mengasumsikan bahwa kedua belah pihak memiliki hingga 8 promosi dan kami masih melakukan yang lebih baik daripada yang terburuk, yaitu 68,613 bit ketika satu memiliki 14 pria dan yang lain memiliki 15 pria.

Perhatikan bahwa ini masih jauh dari menjadi representasi yang sempurna, karena memungkinkan banyak posisi ilegal.

Kode untuk menghitung tabel permutasi:

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

    }
}

Bagaimana Anda menyimpulkan posisi para raja? Anda menggunakan 15 orang dalam perhitungan Anda dan tidak ada bit khusus untuk posisi raja.
Alin Stoian

@AlinStoian, oops. Saya memiliki <daripada <=di loop output dari program saya. Terima kasih telah menunjukkannya. Saya masih bisa memulihkan skor sebelumnya dengan casing khusus ke-32 pria yang ada di papan, tapi saya tidak akan melakukannya sekarang.
Peter Taylor

Data yang menarik! Kasus terburuk teoretis dengan 3 orang ditangkap
Level River St

@steveverrill, apa yang benar - benar ingin saya lakukan adalah mengkodekan posisi pion dan jumlah promosi dalam satu "blok" dan kemudian posisi potongan dan nilai-nilai. Namun, setidaknya ada 2 posisi pion 38 tanpa memperhitungkan promosi akun, dan menghitung mereka secara efisien sejauh ini lolos dari saya.
Peter Taylor

@petertaylor Jika Anda hanya memiliki 16 pion di papan, dibatasi hingga 48 kotak, Anda memiliki 48! / 32! / 8! / 8! = 29019905518636890 kemungkinan. Sedikit lebih dari 2 ^ 54! Dari jumlah tersebut, beberapa di antaranya ilegal, Anda tidak dapat memiliki semua pion dengan satu warna di satu sisi papan.
Level River St

5

178 bit (174 dalam keadaan darurat!) Kasus terburuk

Hai, baru saja kembali ke pengkodean, yang belum pernah saya lakukan sejak kuliah. Saya melihat situs ini dan berpikir ini terlihat menarik. Saya melakukan sedikit pemeriksaan teoritis dan tampaknya setidaknya 146 bit diperlukan untuk algoritma yang sempurna, mungkin beberapa lagi (saya akan menjelaskan dalam komentar ketika saya punya waktu.)

Bagaimanapun, ini adalah cara saya menyusun data. Konsep dasar datang pada 178 bit, tetapi dengan beberapa pokery jiggery dapat diturunkan ke 174 (itu 21 3/4 byte). 175 sedikit lebih mudah diprogram, lebih bisa dibaca oleh manusia, dan masih dalam 22 byte.

A) Posisi kedua raja: masing-masing 6 bit untuk putih dan hitam 12 BIT

B) Dari 62 kotak yang tersisa, yang ditempati? Matriks 62 BITS

C) Giliran siapa itu? 1 BIT

JUMLAH JAUH: 75 BIT

D) En Passant. Jika giliran putih untuk bergerak, hingga 5 pion hitam mungkin terlihat seperti bisa ditangkap En Passant. Gadai hitam harus berada di baris 5 (dari bawah ke atas mulai dari nol), dan memiliki gadai putih di sebelahnya. Satu situasi dengan jumlah tangkapan maksimum yang mungkin terlihat seperti ini:

BWBBWBBW

Jika ada 6 pion hitam di baris 5, putih hanya akan memiliki 2 kotak untuk berdiri dan hanya bisa mengancam 4 pion hitam, jadi tidak mungkin untuk memiliki lebih dari 5 pion hitam yang tampaknya di bawah ancaman dari orang yang lewat pada saat yang sama. Jadi kita memerlukan angka 1 hingga 5 yang menunjukkan pion mana (hingga 5) pada baris 5 yang memiliki pion yang bermusuhan (dalam hal ini putih) di sebelahnya adalah maju 2 kotak pada belokan terakhir ( atau, nol jika tidak ada bidak dalam situasi ini dipindahkan dengan cara ini pada belokan terakhir.)

E) Dari 30 kotak yang ditempati (tidak termasuk raja), apa isinya?

Ada 10 kemungkinan, masing-masing diwakili oleh angka desimal.

Bit paling signifikan mewakili warna.

Karenanya bilangan genap putih, angka ganjil hitam.

Putih hitam

Gadai 0/1 (atau Benteng yang diizinkan menuju kastil *)

Ksatria 2/3

Uskup 4/5

Benteng 6/7

Ratu 8/9

* Benteng yang diizinkan untuk dikastil (dan karena itu tidak pernah dipindahkan dari baris pertama atau terakhir) diwakili oleh 0 atau 1 bukannya 6 atau 7. Tidak dapat dikacaukan dengan pion, karena pion tidak dapat ditemukan pada baris pertama. atau baris terakhir.

Ini memberikan angka desimal hingga 30 digit, yang dapat kita kalikan dengan 6 dan kemudian menambahkan kode untuk En passant. Angka yang dihasilkan akan masuk ke dalam 103 bit, yang bila ditambahkan ke 75 yang disebutkan di atas adalah 103 + 75 = 178 bit . Sebenarnya, jika kita hanya mengalikan 10 daripada 6, tidak ada bedanya dengan jumlah bit yang digunakan, dan decoding lebih mudah.

Ini hanya 2 bit lebih dari 22 byte. Namun kita dapat menekannya ke 174 bit, seperti yang dijelaskan di bawah ini.

Jika tidak ada bagian yang ditangkap, maka gadai tidak mungkin dipromosikan .

Buktinya adalah sebagai berikut. Bayangkan putih terobsesi dengan mempromosikan pionnya pada (misalnya) kolom E, sejak awal permainan. Ada pion hitam di seberang pion ini yang menghalangi. Karena itu untuk mempromosikan pion ini, salah satu dari yang berikut harus terjadi:

1) Gadai hitam ditangkap.

2) Gadai hitam menangkap bagian lain dan karena itu bergerak keluar dari jalan.

3) pion putih menangkap pion pada kolom yang berdekatan seperti kolom D.

4) pion putih melewati (atau dilewati) pion hitam pada kolom yang berdekatan dan kemudian menangkap potongan pada kolom yang berdekatan yang sama, menyebabkan pion putih mengubah kolom.

Kasus 4 adalah yang paling menarik, karena bukan hanya pion putih yang dimulai pada kolom E yang sekarang memiliki jalur promosi yang jelas. Gadai hitam pada kolom yang tetap di kolom E juga dapat mempromosikan. Oleh karena itu satu tangkapan dapat membersihkan jalan bagi satu gadai dari setiap warna untuk dipromosikan.

Ngomong-ngomong, fakta bahwa tidak ada gadai yang bisa dipromosikan sampai karya diambil berarti kita tidak harus menyimpan karya ke-30. Kita dapat mengatasinya dengan eliminasi (atau dengan pengurangan, karena seperangkat kode bagian lengkap pada awal permainan selalu bertambah hingga jumlah yang sama = 80.) Satu poin kecil adalah bahwa kita harus memastikan bahwa kotak di mana rooks berdiri di awal permainan adalah di antara yang dipindai pertama (karena jika mereka terakhir, kita tidak akan tahu apakah benteng bisa benteng atau tidak.) Ini mudah dilakukan dengan memindai baris 0 dan kemudian baris 7 ke 1: Untuk r = 8 hingga 1 memindai baris [r mod 8].

Jadi, matriks bit dalam (B) akan memberi tahu kami berapa banyak potongan yang ada (tidak termasuk raja.) Jika ada 30 bit penuh, abaikan potongan terakhir saat pengkodean, decoder akan mencari tahu apa itu. Kami sekarang memiliki angka desimal hingga 29 digit, yang kami kalikan dengan 6 dan tambahkan ke kode Passant. Jumlah yang dihasilkan hanya akan diperas menjadi 99 bit, memberikan total 99 + 75 = 174 bit.

Sebagai contoh Inilah posisi aktual. Putih baru saja membuat langkah pertamanya (bidak raja maju) dan giliran Black`s.

rnbqkbnr
pppppppp


    P

PPPP PPP
RNBQKBNR

A) Posisi raja (Putih / Hitam dalam oktal, 12 bit ): 03 73 = 000011 111011

B) Kotak mana yang ditempati? Mulailah dengan baris nol (baris bawah) kemudian semua baris lainnya dari atas ke bawah, lewati raja-raja:

1111 111

1111 111
11111111
00000000
00000000
00001000
00000000
11110111 

C) Giliran Hitam: Putar Bit = 1

D) En Passant. Tidak ada pion putih di sebelah pion hitam, oleh karena itu tidak ada pion yang dapat diambil secara bersamaan (meskipun pion ini memang memajukan gerakan terakhir) jadi D = 0. Jika, alih-alih hanya mempertimbangkan pion yang memiliki pion yang bermusuhan di samping mereka, kami menganggap semua pion yang tidak memiliki bidak ramah di samping mereka di kedua sisi, maka D akan menjadi 1, karena ada satu bidak dalam situasi ini, dan ini khususnya pion itu memang tergerak pada belokan terakhir.

E) Sekali lagi, baris bawah pertama, lalu semua baris lainnya dari atas ke bawah, melompati raja-raja, dan dengan empat benteng yang belum diputar disebut sebagai 0 atau 1 (angka biasanya dicadangkan untuk pion.)

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

Digit ke-30 (dalam kurung) dapat dibuang.

Meskipun tidak terlalu jelas di sini, pion yang White telah maju sebenarnya ada di salah satu ujung daftar pion, karena kami memindai baris demi baris.

Data kami sekarang terlihat seperti ini, dengan 29 kode untuk isi kuadrat, ditambah kode En Passant:

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

Yang terbaik adalah memindai dari kanan ke kiri saat decoding dan dari kiri ke kanan (urutan terbalik) saat encoding. Ini berarti bahwa ketika ada potongan yang lebih sedikit kita akan memiliki jumlah yang lebih kecil, sambil mempertahankan konsistensi maksimum (yaitu kita ingin ruang kosong / nol menjadi yang terdepan, tidak tertinggal, untuk memungkinkan kompresi papan yang jarang ditempati.) Ketika kita hanya memiliki 2 raja di papan tulis, kita akan memiliki 75 bit yang disebutkan di atas, ditambah 3 bit untuk menyimpan data yang lewat = 78 bit dalam kasus terbaik. Setiap potongan tambahan datang sedikit di bawah 3,5 bit (2 buah dapat disimpan dalam 7 bit, karena 100 <128.)

Ada masalah praktis dalam bilangan bulat 99 bit yang terlalu besar untuk ditampung dalam variabel bilangan bulat 64 bit, yang berarti banyak bahasa pemrograman tidak memberikan dukungan untuk itu (Anda tidak bisa begitu saja mengubah representasi string dari 29-30 digit angka menjadi bilangan bulat.) Sebagai cara mudah pengkodean untuk 22 byte, kita dapat memecah angka 30 digit (29 kode potong + en kode passant) menjadi dua angka 15 digit yang masing-masing akan muat dalam 50 bit masing-masing (total 100 bit ditambah 75 yang disebutkan di atas membuat 175 bit kasus terburuk.)

Untuk kompresi maksimum, seperti yang dinyatakan di atas, 29 angka desimal ditambah kode En Passant (6 nilai yang mungkin), hanya akan masuk ke dalam 99 bit (dengan total 174 bit) tetapi tanpa dukungan dari bahasa untuk bilangan bulat ukuran ini adalah rumit untuk diprogram. Mungkin lebih mudah untuk memisahkan 29 bit warna dan bekerja dengan kode tipe piece (5 kemungkinan) dan kode Passant (6 kemungkinan) secara terpisah dari warna (70 bit, hampir cocok menjadi variabel 64 bit.)


Trik yang bagus dengan pria terakhir.
Peter Taylor

5

Berikut ini adalah solusi lengkap, kasus terburuk aktual 181 bit

Fokus di sini adalah program sederhana yang dapat Anda pahami dengan mudah

Input adalah FEN, di sini adalah posisi pembukaan, memiliki enam bidang (5 & 6 diabaikan):

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

Bidang pertama (penempatan potongan) diuraikan

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

Untuk menghasilkan:

rnbqkbnrppppppp________________________________PPPPPPPPRNBQKBNR

Field satu: mengkodekan lokasi raja (12 bit):

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

Bidang dua: menyandikan potongan (hingga 5 bit per potong):

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

Bidang tiga: warna aktif (1 bit)

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

Bidang empat: ketersediaan castling (4 bit)

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

Bidang lima: en passant (nol atau 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

Kasus terburuk naif 200 bit

  • Dua penempatan raja - 12 bit
  • Naik
    • QRRBBNN QQQQQQQQ - 75 bit
    • qrrbbnn qqqqqqqq - 75 bit
    • Kotak kosong - 30 bit
  • Warna aktif - 1 bit
  • Castling - 4 bit
  • En Passant - 3 bit

Kasus terburuk aktual

Setiap pemain tidak dapat mempromosikan semua pion tanpa menangkap bagian lainnya . Berikut adalah efek entropi dari penangkapan potongan:

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

Jadi sebenarnya papan kasus terburuk adalah:

  • QRRBBNN QQQQQQQQ - 75 bit
  • qrrbbnn qqqq - 55 bit
  • Kotak kosong - 34 bit

Kasus terburuk adalah mempromosikan semua bagian daripada meninggalkan pion untuk orang yang lewat.

TOTAL KASUS TERBURUK AKTUAL DENGAN SHOWN KODE 12 + 75 + 55 + 34 + 1 + 4 = 181 bit

FIQ menunjukkan dua peningkatan pada skema sederhana ini, tetapi mereka lebih sulit untuk dikodekan:

  • Hapus bit 2 dari bagian encoding pada baris 1 dan 8 karena pion tidak bisa pergi ke sana (penghematan hingga 16 bit)
  • Gunakan pion untuk menyandikan benteng castable (penghematan 4 bit)

Satu-satunya kode yang tersisa tidak ditampilkan dalam jawaban ini (untuk singkatnya) adalah: memecah input FEN di bidang ( split /\s/) dan penugasan variabel.


Seorang pemain dapat mempromosikan semua pionnya (Mengingat bahwa ia mampu menangkap pion musuh); Qn4QQ / Qb6 / Qq1k4 / Qr6 / Qb6 / Qr6 / Qn4NK / RNB2B1R b - - 0 84
Krzysztof Szewczyk

@ KrzysztofSzewczyk, ya itu tercantum di atas di PPpp=>QQq_
William Entriken

4

Total data membutuhkan 33 byte

(Terima kasih kepada seseorang di komentar saya menyadari ini tidak berfungsi untuk promosi gadai. Akan memperbarui ini ketika saya bisa menyelesaikannya)

untuk byte pertama kita menggunakan lima bit:

  • bit pertama: giliran pemain, 1 = putih
  • bit kedua: kastil sisi raja hitam, 1 = kastil can
  • bit ketiga: kastil sisi ratu hitam, 1 = kastil can
  • bit keempat: kastil sisi raja putih, 1 = kastil can
  • bit kelima: kastil sisi ratu putih, 1 = kastil can

32 byte berikutnya digunakan untuk mewakili setiap bagian catur, dalam urutan yang telah ditentukan

  • 3-bit: mewakili baris
  • 3-bit: mewakili kolom
  • 1-bit: mewakili en-passant, 1 = can en-passant
  • 1-bit: jika "can en-passant" bit adalah 1: menunjukkan sisi mana, 0 = kiri yang
    lain menunjukkan apakah ia telah ditangkap. 0 = tidak ditangkap
    (Jika bisa en-passant maka pasti tidak ditangkap)

Beberapa kode C untuk mewakili ide ini (yang sebenarnya tidak berfungsi)

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, ini bukan jawaban ...
Gagang Pintu

1
Pesanan Anda yang sudah ditentukan sebelumnya tidak akan banyak berguna ketika pion mencapai peringkat kedelapan dan dipromosikan menjadi ksatria, uskup, benteng atau ratu.
lubang peringatan melengking

@Doorknob dari Snow ok saya sedang mengerjakan algoritme, ini hanya sedikit larut malam dan saya lelah, jadi saya melakukannya sedikit lebih lambat
pastebin.com memangkas 0mr8spkT

Lalu mengapa Anda memposting ini jika Anda bahkan tidak punya solusi?
Gagang Pintu

3
jika Anda masih menganggap jawaban ini omong kosong dan tidak memiliki nilai di sini, silakan pilih untuk menghapus dan membatalkannya dan Anda juga dapat menghapus akun saya di sini. saya hanya ingin berbagi apa yang bisa saya pikirkan, mengapa kalian harus begitu kejam?
pastebin.com memangkas 0mr8spkT

4

256 242 bit

Berikut adalah algoritma kompresi dasar yang mungkin dapat ditingkatkan karena tidak mengecualikan posisi ilegal tertentu dari yang diwakili.

Papan dimulai dengan 5 bit informasi header, sebagai berikut:

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

Kemudian, string 12 bit mewakili posisi raja.

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

Kemudian, angka 64-digit yang sangat besar pada basis 11, yang kemudian dikalikan dengan 9 untuk menambahkan digit lain pada bagian akhir yang mewakili keadaan en-passant. Setiap digit pada basis 11 mewakili sebuah persegi di papan tulis, dengan nilai-nilai berikut yang mungkin:

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.

Dan digit pada basis 9:

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

11 64 × 9 adalah sekitar 2 224.57 , yang membutuhkan 225 bit untuk dikodekan. Ditambah 17 bit tajuk di bagian atas, adalah total 242 bit.


Terima kasih ugoren untuk perbaikannya.


Ini sangat mirip dengan algoritma ace, tetapi menggunakan posisi dewan alih-alih bagian-bagian dalam urutan yang telah ditentukan, yang keduanya mengecualikan dari memiliki masalah promosi gadai dan memungkinkan data untuk dipotong sedikit.
Joe Z.

Anda dapat menyimpan en-passant sebagai satu angka antara 0 dan 8 (di kolom mana pemain saat ini dapat menangkap en-passant?). 13^64 * 9adalah 239,99, menghemat 11 bit. Simpan lebih banyak dengan mengode posisi raja secara terpisah.
ugoren

Menurut Doorknob of Snow yang berkomentar di posting saya, jawaban semacam ini adalah "bukan jawaban". Hanya mengatakan. FYI komentarnya diposting sebelum saya menambahkan kode C ke jawaban saya.
pastebin.com memangkas 0mr8spkT

@ugoren: Saya lupa tentang itu. Anda benar, saya lupa bahwa hanya satu pion yang dapat melintas pada saat yang sama.
Joe Z.

@ace: Jawaban Anda tidak valid karena tidak menyertakan kode penyandian dan pendekodean; itu tidak valid karena tidak memperhitungkan kasus promosi gadai (dalam hal ini urutan potongan yang Anda tentukan tidak melakukan apa-apa). Masalahnya, pada intinya, meminta skema pengkodean data. Program ini hanya sesuatu untuk berinteraksi dengan itu.
Joe Z.

3

? bit

(≥ 217 terburuk, 17 terbaik, 179 untuk papan awal)


Deskripsi pengodean

Metadata tambahan terdiri dari giliran siapa (satu bit) dan castling (empat bit, yaitu kastil putih di sisi raja 'di sisi ratu' dan juga untuk hitam).

Untuk posisi papan itu sendiri, kami menyandikannya sebagai satu set potongan aktif. Sebenarnya, kami memastikan untuk menghitung satu per satu bagian dengan urutan tertentu untuk alasan yang akan saya jelaskan sedikit. Untuk setiap bagian kami menyimpan warnanya (satu bit), jenisnya (tiga bit untuk mencakup 6 jenis, ditambah satu jenis tambahan untuk "pion yang dapat diambil oleh en passant"), serta posisinya.

Inilah bagian yang menarik: untuk menyandikan posisi potongan, alih-alih menyimpannya sebagai koordinat, kami menyimpan jarak relatifnya dari potongan terakhir ketika menghitung bagian-bagian dalam urutan kiri-ke-kanan, atas-ke-bawah (yaitu A8 , B8, ..., G1, H1). Selain itu, kami menyimpan jarak sebagai angka panjang variabel, menggunakan 1berarti bahwa bagian ini tepat di sebelah sebelumnya, 0xxuntuk melewatkan 1-3 buah, 000xxxuntuk melewatkan 4-10 buah, 000000xxxxuntuk 11-25, 0000000000xxxxxuntuk 26-56 dan akhirnya 000000000000000xxxuntuk 57-62.

Contohnya

Saya membuat intisari dari beberapa posisi yang dikodekan dengan pengkodean ini, dan menjelaskannya untuk posisi awal dengan beberapa komentar.

Saya tidak tahu bagaimana menganalisis ukuran bit terburuk, tetapi dengan contoh-contoh di intinya, saya percaya bahwa algoritme setidaknya harus agak efisien.


Implementasi decoder

Di bawah ini adalah dekoder cepat dan kotor untuk pengkodean ini (mengambil sebagai input data biner yang dikodekan dalam teks, seperti dalam contoh beranotasi di atas, dan melompati hal-hal yang bukan '0' atau '1'). Menghasilkan papan catur unicode ke 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;
}

Saya tidak tahu berapa jumlah bit terburuk Anda, tapi saya kira ini lebih dari 179 bit. Misalnya, bagaimana algoritma Anda menangani tata letak ini ? (Ini adalah valid, dengan cara; aku berhasil menggunakan editor di chess.com )
mual ossifrage

@squeamishossifrage yang tampaknya membutuhkan 217 bit: gist.github.com/FireyFly/8639791 (terima kasih untuk test-case, saya ingin mencobanya dengan yang lebih sulit!)
FireFly

Hei, itu tidak buruk. Teruskan!
ossifrage pelit

2

Maks: 184 bit, Min: 75 bit

Saya terinspirasi oleh kode Huffman dari @SammSpeight untuk mencoba membuat skema sendiri. Saya ragu ini akan menang, tetapi memang memiliki batas yang dapat dihitung.

Skema ini memperlakukan bidak catur seolah-olah ada 11 jenis bidak yang berbeda. Saya kira-kira mengikuti algoritma pengkodean Huffman untuk mengelompokkan kelas-kelas ini berdasarkan frekuensi dan tipe nyata untuk menghasilkan pengkodean berikut:

 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

Kode masing-masing bagian dapat didahului oleh dua bit untuk menunjukkan ke tim mana ia berada ( 10untuk Putih, 11untuk Hitam). 0dapat digunakan untuk menyandikan ruang kosong. Ide-ide ini memungkinkan kita untuk membangun encoding persegi-demi-persegi untuk seluruh papan menggunakan prosedur apa pun yang kita inginkan. Saya akan menganggap urutan iterasi a1, b1, c1, ... f8, g8, h8. Ini berarti bahwa hanya daftar kode-kode ini seperti yang ditunjukkan di atas mengkodekan semua informasi kecuali giliran siapa. Mesin catur yang sangat sederhana dapat menggunakan "kelas" untuk bidak, benteng, dan raja untuk menentukan apakah castling dan en passant adalah legal. Selain itu, skema ini dengan mudah menangani promosi gadai. Jika seorang pemain mempromosikan pion ke benteng, baik kode raja atau sisi ratu dapat digunakan selama varian "dipindahkan" dipilih.

Kecuali posisi patologis yang saya pikir tidak akan pernah bisa terjadi, skenario terburuk untuk pengkodean ini adalah ketika semua bagian masih ada di papan dan pemain sebelumnya memindahkan pion ke depan dua ruang. Sebagai contoh, papan di bawah ini menyandikan 1. e4:

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

Ini berarti bahwa pengkodean terburuk memiliki 184 bit: 1 untuk menunjukkan pemain, 32 untuk ruang kosong, 45 untuk pion yang tidak bergerak, 6 untuk pion melompat dua ruang, 24 untuk para ksatria, 24 untuk para uskup, 28 untuk para benteng, 12 untuk para ratu, dan 12 untuk para raja.

Saat potongan bergerak dan ditangkap, ukuran pengkodean akan turun. Skenario kasus terbaik diwakili oleh dua raja saja di papan: 1 bit untuk menunjukkan pemain + 62 bit untuk menunjukkan kotak kosong + 12 bit untuk menunjukkan raja memberikan panjang minimum 75 bit.

Saya akan kembali dan mengedit respons ini dengan beberapa kode yang menunjukkan tindakan encoding ini hari ini atau besok. Untuk saat ini, saya ingin tahu apa pendapat orang lain tentang pengkodean ini.


1
Anda dapat menyimpan bit di benteng. Anda dapat menentukan sisi ratu dan raja berdasarkan posisi, dan Anda tidak perlu tahu dari sisi mana rook-move berasal. jadi Anda hanya perlu sedikit informasi tentang benteng - dipindahkan atau tidak dipindahkan.
Bukannya Charles

... Dan sebenarnya, menyimpan data tersebut pada level per satuan lebih mudah untuk disandikan / didekode, tetapi jika Anda baru saja menyimpan penanda di awal, Anda dapat menyimpan bit keseluruhan kasus terburuk (misalnya, 11001sarana penanda B'S MOVE W CAN KSC W CANT QSC B CANT KSC B CAN QSC). Itu adalah 4 bit, bukan 5 bit per sisi dalam pengkodean Anda, atau 3 bit per sisi jika Anda menghilangkan penanda sisi pada benteng. ( KSC= Kastil sisi- QSCraja . = Kastil sisi-ratu)
Bukan berarti Charles

Juga, karena promosi, sangat mungkin untuk memiliki hingga 9 Ratu atau 10 Ksatria (atau karya non-agung, non-gadai lainnya)
Bukan karena Charles

1

184 bit = 23 byte kasus terburuk, dan tidak terlalu rumit:

A. Kotak mana yang ditempati: 64 bit = 8 byte B. Yang warna untuk <= 32 kotak yang ditempati: 32 bit = 4 byte Dan sekarang hanya menggunakan <= 30 kotak yang ditempati oleh bukan raja: B. gunakan PNBRQ yang disandikan dalam radix 5, untuk 5 ^ 30 kemungkinan; dan 32 * 31 * 2 * 4 * 4 * 9 untuk posisi raja, warna penggerak, hak castling putih & hitam, en passant square (di antara 8 kemungkinan plus tidak ada, ke-9); angka ini 5 ^ 30 * 32 * 31 * 2 * 4 * 4 * 9 = 266075134277343750000000000 = 2 ^ 87,782 cocok dalam 88 bit untuk total 64 + 32 + 88 = 184 bit untuk seluruh pengkodean.

Ini dapat dikurangi, mis. 32 * 31 * 2 * 4 * 4 * 9 = 285696 dapat dikurangi menjadi 2 * (32 * 31 + 31 * 3 + 31 * 3 + 3 * 3) * 6 = 14244, dengan menggunakan fakta paling banyak 6 kandidat korban yang lewat (termasuk tidak ada), dan mengkodekan hak-hak pemeran dan posisi raja dalam set yang sama menggunakan hak-hak pemerasan fakta hanya penting ketika raja di lapangan awal. Ini menghemat 4 bit.

Saya punya alasan untuk percaya bahwa tidak mungkin mencapai 18 byte, yaitu jumlah total posisi catur legal melebihi 2 ^ 144.

Skema 160-bit Anda sangat cerdik tetapi saya pikir ini perlu diberikan sebagai program encode / decode sebelum saya benar-benar yakin tentang hal itu.


1

171 bit kasus terburuk:

Saya telah menggabungkan beberapa ide, dan juga beberapa pemikiran saya sendiri.

Kita akan mulai dengan papan 64 bit. Setiap bit mewakili ruang yang ditempati di papan tulis. Mereka mengisi baris. Jadi awalnya terlihat seperti:1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111

Sekarang, masing-masing bagian akan diwakili oleh 4 bit. Bit 1: warna ( 0=white, 1=black) Bit 2-4: Satu dari 8 jenis.

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

Pada akhirnya kami akan menyertakan sedikit menunjuk gilirannya. 0=white, 1=black.

4bits * 32 pieces = 128 bit dan saya sudah mendapatkan 64 +1 dari turn and board. Itu menghasilkan total 128 + 64 + 1 = 193 Saya bahkan belum mulai dengan en passant atau castling. Lebih dari batas saya dengan apa-apa - bahkan tidak berubah. Di sinilah trik dimulai.

Oke - Anda melihat tipe di atas? Bishop0 dan Bishop1? Pion0 dan pion1? Jenis-jenis itu sangat ditentukan, karena mereka memberi tahu kami sedikit untuk memasukkan setelah bagian ini. Jadi Bishop0 berarti bahwa setelah itu, akan ada 0 - yaitu bahwa potongan berikutnya berwarna putih. Bishop1 memberi tahu kita bagian selanjutnya berwarna hitam, dan pion0 dan pion1 bekerja sama. (Jika bagian ini adalah bagian terakhir yang disebutkan, maka itu memberi tahu kita tentang giliran berikutnya).

Kasus terburuk saya melibatkan semua bagian di papan tulis, jadi dengan 16 pion dan 4 uskup, ini menghemat 20 bit. Saya turun ke 173.

Baik. Untuk bit lain dalam kasus terburuk saya - setelah ada 16 warna yang dikodekan, kami berhenti mengkodekan warna - seperti yang kita tahu akan maju. Kasus terburuk saya sekarang melibatkan sepotong putih membuatnya ke sudut jauh tanpa tangkapan. Di sana, saya hanya menyimpan sedikit. 172.

Sekarang saya akan mengubah urutan yang saya beri nama. Kami akan menamai mereka di sepanjang kolom mulai dari luar bergerak masuk. Papan bernama di awal akan tetap sama, tetapi ketika saya menempatkan potongan di atasnya, saya mulai dari kanan bawah putih, dan naik kolom itu. Lalu aku melompat ke kanan bawah hitam, dan naik ke kolom itu. Saya melompat ke sel putih yang tidak diketahui kanan bawah, dan sebagainya - ini berarti kasus terburuk saya adalah awal lagi. Alasan saya ada hubungannya dengan trik en passant saya, dua bit berikutnya yang saya hilangkan, dan kasting.

Sekarang, untuk gadai yang akan dipromosikan (seperti yang telah dibahas panjang lebar) sepotong harus ditangkap. Jadi, ketika kita tahu ada 32 buah, kita hanya perlu menunjukkan 31 dari mereka. Bagian terakhir diidentifikasi secara unik. Ternyata, bagi saya, ini hanya menghemat 2 bit - karena bagian terakhir saya mungkin pion / uskup (yang biasanya harganya 3 bit karena saya menyimpannya satu pada bagian berikutnya) yang warnanya sudah ditentukan dan jadi hanya 2 bit. Saya turun ke 170 bit.

Ketika pion dipromosikan, mereka hanya mengubah tipenya. Untuk setiap bagian yang keluar dari papan saya membebaskan diri dari (minimum) 3 bit, dan dua promosi gadai harganya 2 bit, jadi saya menolak (perlahan) dalam promosi.

Castling. Agar kastil terjadi, raja atau benteng yang relevan mungkin tidak bergerak. Dengan demikian, ketika sebuah benteng mampu melemparkan keduanya dan raja akan berada di tempat asalnya. Jadi, benteng yang mampu melakukan castling akan terdaftar di tempat yang sama dengan raja-raja dengan warna itu. Karena ini ilegal (dua raja atau tiga raja dengan warna yang sama di papan tulis) dan hanya dapat terjadi dalam tiga pengaturan yang memungkinkan untuk setiap warna (kiri, kanan, kedua benteng didaftar sebagai raja) - penguraian sandi sangat mungkin dilakukan. Jadi, tanpa bit kita telah mengkodekan castling.

En Passant Di sini kami juga akan menggunakan posisi ilegal. Hanya satu bidak yang bisa berada dalam bahaya saat lewat. Itu harus di baris keempat. Gadai yang rentan akan 'dibalik' kembali ke barisan rumahnya - diganti dengan apa pun yang ada di sana. Karena pion itu berada di baris pertama - posisi ilegal, situasinya akan jelas bagi decoder - itu akan membalik posisi, dan menandai pion sebagai rentan terhadap pelintas.

Kami perlu bercampur dengan pesanan karena bagian terakhir harus 'diidentifikasi secara unik'. Dalam urutan standar, kita tidak akan bisa tahu apakah benteng di sudut belakang bisa kastil - itu tidak diketahui. Ketika kami bekerja dari luar ke dalam, kami menjamin bahwa di mana pun benteng itu 'terdaftar' baik itu di sudutnya sendiri, atau di tengah papan karena diganti dengan pion rentan yang lalu lalang, akan ada bagian yang terdaftar setelah itu - jadi kita diberitahu tipe benteng. Kita tahu akan ada bagian setelahnya karena, agar gadai menjadi rentan harus ada gadai di dalamnya (yang akan dikodekan nanti sesuai dengan instruksi di atas).

Oh, dan untuk memastikan bahwa kasus terburuk melibatkan semua bagian di papan tulis, setelah kita memiliki kurang dari 32 bagian, kita dapat menggunakan papan 64 bit untuk mengidentifikasi posisi serta posisi yang ditempati dengan menggunakan 0 untuk mewakili bagian ketika bagian putihnya berbalik dan 1 ketika giliran orang kulit hitam.

Jadi kami bebas dan kastil secara gratis. Kami mengambil bagian terakhir secara gratis, meskipun butuh beberapa finagling untuk membuatnya bermain bagus dengan aturan en passant dan castling. Kami membuang 20 bit pada potongan standar. Saya percaya kasus terburuk di sini melibatkan pion putih tengah bergerak maju dan sepotong hitam di antara itu dan ratu sementara semua bagian ada di papan tulis. Periksa cepat: bagian pertama ditangkap - sebut saja pion, 3 bit dari papan di pion, 3 bit di papan dalam bentuk bagian terakhir, satu bit di penanda belok menghilang. Promosikan dua bidak 2 bit kembali di papan tulis. Ah sial, aku di 171.

EDIT Saya telah menambahkan kode untuk decoder (berfungsi?) - di R - di bawah. Dibutuhkan vektor booleans sebagai input - (maaf - saya tidak mampu mengkode dengan baik dalam hal apa pun yang akan membuat saya benar-benar menggunakan bit) Saya juga sudah memasukkan posisi awal.

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

Kode ini membangun 4 fungsi. Salah satu yang melakukan pemisahan dasar dari potongan-potongan dan struktur papan, serta mencari tahu jenis potongan dan setiap potongan 'implisit'. Fungsi selanjutnya mengisi struktur papan dengan potongan-potongan dalam urutan yang sedikit aneh (dan berbeda dari algoritma awal saya) [dijelaskan dalam komentar kode]. Fungsi selanjutnya mengambil papan yang terisi dan mendeteksi posisi ilegal - kemudian memperbaikinya dan mengganti nama pion yang rentan terhadap en passant "x pawn-e" dan setiap benteng yang dapat benteng "x rook-c". Fungsi terakhir adalah pembungkus yang menjalankan fungsi-fungsi tersebut secara berurutan dan memberikan output yang merupakan papan saat ini serta gilirannya.

Saya juga menyertakan penyandian posisi awal (meskipun untuk melihatnya Anda harus memanggil c(startboard,newpieces)dan kode memanggil fungsi wrapper pada posisi itu.


Ini menarik. Saya ingin melihat implementasi yang berfungsi sebagai bukti konsep.
Mego

Implementasi biasanya beberapa langkah di luar bukti konsep, tetapi saya telah menambahkan decoder. Itu dalam R dan dengan demikian menggunakan Boolean daripada bit (maaf - tidak ingin menggunakan terlalu banyak waktu). Tapi saya percaya itu harus menjadi bukti konsep.
user5957401

0

229/226 bit

Ini ternyata tidak terlalu berhasil, tetapi mungkin menyelamatkan orang lain melalui jalan yang sama.

Versi sederhana:

  • 1 bit untuk giliran siapa
  • 4 bit untuk empat kemungkinan casting
  • 3bit untuk en passant kemungkinan. Ini memiliki kedalaman yang saya mengerti pada awalnya. En passant harus dilakukan oleh pion yang bergerak dari pangkat (baris) yang sama dengan pion yang ditangkap. Analisis kasus menunjukkan bahwa setelah kita tahu berapa banyak bidak warna yang terakhir pindah telah maju tepat dua kotak, akan ada paling banyak 6 en passant kasus (termasuk kasus yang tidak ada pion rentan terhadap sambil lalu ). Kasus terburuknya adalah 5 pion (berpotensi semua rentan: misalnya PpPPpPPpmemiliki lima rentan P). Dengan 6 pion ada paling banyak 2 pion musuh di peringkat yang sama, yang masing-masing bisa mengancam paling banyak 2 pion dalam perjalanan . Karena itu kita perlu ceil(lg 6) = 3bit di sini.

Lalu papan tulis. Papan memiliki 64 kotak, sehingga indeks kuadrat dapat dikodekan dalam 6 bit. Kami membuat daftar para lelaki berdasarkan pangkat, bergantian warna, mulai dari raja.

  • 6bit: posisi raja putih. (Dijamin akan berada di papan tulis).
  • 6bit: posisi raja hitam. (Dijamin berada di papan tulis. Dalam kasus terburuk bahwa raja kulit putih ada di sudut, ada 60 tempat yang mungkin dia bisa; dalam kasus terbaik bahwa putih tidak berada di tepi, ada 55).
  • 6bit: posisi ratu putih. Jika tidak ada ratu putih, ulangi posisi raja putih sebagai sinyal.
  • Untuk setiap ratu putih tambahan, 1sedikit diikuti oleh 6 bit untuk posisi.
  • Sebuah 0sedikit.
  • Ditto untuk ratu hitam.
  • Proses serupa untuk benteng, uskup, ksatria, dan pion, meskipun kita bisa melewatkan pion untuk warna jika kita sudah memiliki 16 orang dari warna yang diperhitungkan.
  • Hapus 0bit terakhir .

Ini menghabiskan 12sedikit demi sedikit untuk raja-raja, dan 2*7*5-1 = 69sedikit untuk yang lain. Dalam kasus terburuk bahwa semua 32 pria di papan tulis, itu biaya 7bit untuk setiap orang selain raja, untuk total 12 + 7*30 - 1 = 221 bits. Jadi dengan 8bit awal untuk kondisi global kita memiliki 229 bit .


Versi lanjutan:

Dengan menggunakan pengkodean aritmatika kita dapat beroperasi dengan lg num_possibilitiesdaripada ceil(lg num_possibilities)dan hanya mengambil satu ceildi akhir.

  • 1 bit untuk giliran siapa
  • 4 bit untuk empat kemungkinan casting
  • lg 6bit untuk en passant kemungkinan.
  • 6 bit untuk raja putih
  • lg 60 bit (kasus terburuk) untuk raja hitam
  • lg 63 bit (karena saya tidak ingin mempersulit ke tingkat melihat cek) untuk ratu putih, menggunakan posisi raja putih jika tidak ada
  • Untuk setiap queen putih tambahan, sebuah 1bit diikuti oleh lg 62, lg 61, dll bit untuk posisinya.
  • Sebuah 0sedikit.
  • lg 63 bit (atau lebih sedikit, jika ada ratu putih) untuk ratu hitam.
  • dll.

Orang ketiga yang benar-benar hadir memiliki 66-nnilai-nilai yang memungkinkan. Jika suatu jenis tidak ada untuk warna, kami menghabiskan 66-#men so farbit dalam merekam itu (ditambah satu bit untuk pemisah). Kasus ekstrim adalah:

  1. Semua lelaki hadir, termasuk setidaknya satu bidak tak berotot dari masing-masing pihak. Kita habiskan 5+lg 6untuk negara global, 6+lg 60raja, 29bit pemisah, dan SUM_{n=32}^{63} lg nbit pada posisi. Total keseluruhan:ceil(225.82) bit. Mengecewakan.
  2. Hanya bidak tanpa promosi yang tersisa. Kita habiskan 5+lg 6untuk negara global, 6+lg 60raja, 29bit pemisah, 8*lg 63mengatakan bahwa tidak ada bagian lain, dan SUM_{n=48}^{63} lg npada posisi pion. Total keseluruhan: ceil(188.94)bit. Lebih baik - dengan menyelamatkan benteng kedua, ksatria, dan uskup untuk setiap sisi kita telah sedikit maju.

Jadi kasus terburuk sepertinya adalah 226 bit , untuk penghematan yang sangat kecil 3.

Kami pasti bisa melakukan yang lebih baik dalam kasus rata-rata dengan menyandikan pion sebelum bagian, karena terbatas pada 48 kotak daripada 64 penuh. Namun, dalam kasus terburuk bahwa semua pria ada di papan tulis dan semua pion telah dipromosikan, saya pikir ini akan berakhir dengan biaya 2 bit lebih karena kita akan memerlukan bendera "tidak ada pion" daripada bisa menghitung laki-laki.


0

Ini adalah topik diskusi di kalangan Catur.

Berikut adalah satu bukti yang sangat sederhana dengan 164 bit https://groups.google.com/forum/#!topic/rec.games.chess.computer/vmvI0ePH2kI 155 ditampilkan di sini http://homepages.cwi.nl/~tromp /chess/chess.html

Lebih dari strategi yang disederhanakan:

  • Batasi pion di tempat pion dapat ditemukan
  • Batasi pasukan untuk mempertimbangkan barang asli dan kemungkinan promosi gadai
  • Berpikir keras tentang promosi dan situasi di mana promosi tidak dimungkinkan

2
Jawaban khusus tautan bukan jawaban yang baik. Anda harus memberikan jawaban lengkap dalam posting Anda, bukan hanya beberapa tautan ke jawabannya. Dan jika jawaban Anda bukan karya Anda sendiri, Anda mungkin harus membuat posting Anda sebagai wiki komunitas.
pastebin.com memangkas 0mr8spkT

Pos asli. Menambahkan detail ke jawaban.
William Entriken

1
Ini adalah contoh mengapa Anda memasukkan konten dalam jawaban Anda. Tautan ke-2 sudah mati. Apakah ini? tromp.github.io/chess/chess.html
mbomb007

-2

Min: 0 bit

Maks: 1734 243 bit (4.335 4,401 bit / papan diamortisasi)

Diharapkan: 351 177 bit (4.376 4.430 bit / papan diamortisasi)

Karena saya dapat menentukan input dan output namun saya ingin saya memutuskan untuk pergi dengan menyandikan sejarah permainan hingga saat ini. Satu keuntungan adalah bahwa informasi tambahan tentang siapa yang mengubahnya, en-passant, dan siapa yang memiliki kemampuan untuk kastil di mana dapat diturunkan dan tidak dikodekan.

Percobaan 1:

Secara naif saya berpikir bahwa saya dapat mengkodekan setiap gerakan dalam 12 bit, 4 triplet dari bentuk (mulai x, mulai y, akhir x, akhir y) di mana masing-masing 3 bit.

Kami akan mengasumsikan posisi awal dan memindahkan potongan dari sana dengan putih akan menjadi yang pertama. Papan disusun sedemikian rupa sehingga (0, 0) adalah sudut kiri bawah putih.

Misalnya gim:

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

Akan dikodekan sebagai:

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

Ini mengarah ke pengkodean 12 m bit di mana m adalah jumlah gerakan yang dilakukan

Di satu sisi ini bisa benar-benar besar, di sisi lain Anda dapat mempertimbangkan setiap langkah untuk menjadi itu game sendiri sehingga setiap encoding benar-benar mengkodekan m "papan catur". Jika Anda diamortisasi ini Anda mendapatkan bahwa setiap "papan catur" adalah 12 bit. Tapi saya merasa ini sedikit curang ...

Percobaan 2:

Saya menyadari bahwa setiap gerakan dalam upaya sebelumnya menyandikan banyak gerakan ilegal. Jadi saya memutuskan untuk hanya menyandikan langkah hukum. Kami menghitung langkah yang mungkin sebagai berikut, beri angka setiap kuadrat sedemikian sehingga (0, 0) → 0, (1, 0) → 1, (x, y) → x + 8 y. Iterasi melalui ubin dan periksa apakah ada sepotong dan apakah itu bisa bergerak. Jika demikian, tambahkan posisi yang dapat dituju ke daftar. Pilih indeks daftar yang merupakan langkah yang ingin Anda buat. Tambahkan nomor itu ke total gerakan yang dibobot oleh 1 ditambah jumlah gerakan yang mungkin.

Contoh seperti di atas: Dari posisi awal, potongan pertama yang bisa bergerak adalah ksatria di kotak 1, bisa bergerak ke kotak 16 atau 18, jadi tambahkan itu ke daftar [(1,16),(1,18)]. Berikutnya adalah ksatria di kotak 6, tambahkan gerakannya. Secara keseluruhan kami mendapatkan:

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

Karena kami menginginkan gerakan (12, 28), kami menyandikan ini sebagai 13 di basis 20 karena ada 20 kemungkinan gerakan.

Jadi sekarang kita mendapatkan nomor g g = 0

Selanjutnya kita melakukan hal yang sama untuk hitam kecuali kita memberi nomor ubin secara terbalik (untuk membuatnya lebih mudah, tidak diperlukan) untuk mendapatkan daftar langkah:

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

Karena kami menginginkan gerakan (11, 27), kami menyandikan ini sebagai 11 di basis 20 karena ada 20 kemungkinan gerakan.

Jadi sekarang kita mendapatkan nomor g permainan 1 = (11 ⋅ 20) + 13 = 233

Selanjutnya kita mendapatkan daftar langkah untuk putih:

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

Karena kami menginginkan gerakan (6, 21), kami menyandikan ini sebagai 13 di basis 29 karena ada 29 kemungkinan gerakan.

Jadi sekarang kita mendapatkan nomor permainan g 2 = ((13 ⋅ 20) + 11) 20 + 13 = 5433

Selanjutnya kita mendapatkan daftar langkah untuk hitam: [(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)]

Karena kami ingin pindah $ (10, 18) $ (10, 18)

Jadi sekarang kita mendapatkan nomor g permainan 3 = (((19 ⋅ 29 + 13) 20) + 11) 20 + 13 = 225833

Dan lanjutkan proses ini untuk semua gerakan yang tersisa. Anda dapat menganggap g sebagai fungsi g (x, y, z) = x y + z. Jadi 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)

Untuk memecahkan kode nomor g permainan 0 , kita mulai dari posisi awal dan menghitung semua gerakan yang mungkin. Kemudian kita menghitung g 1 = g 0 // l , m 0 = g 0 % l , di mana l adalah jumlah gerakan yang mungkin, '//' adalah operator pembagian integer dan '%' adalah operator modulus. Seharusnya menyatakan bahwa g 0 = g 1 + m 0 . Selanjutnya kita buat langkah m 0 dan ulangi.

Dari contoh di atas jika g 0 = 225833 maka g 1 = 225833 // 20 = 11291 dan m 0 = 225833% 20 = 13. Selanjutnya g 2 = 11291 // 20 = 564 dan m 1 = 11291% 20 = 11. Kemudian g 3 = 11291 // 20 = 564 dan m 2 = 11291% 20 = 11. Karena itu g 4 = 564 // 29 = 19 dan_m_ 3 = 564% 29 = 13. Akhirnya g 5 = 19 // 29 = 0 dan m 4 = 19% 29 = 19.

Jadi berapa banyak bit yang digunakan untuk meng-encode game dengan cara ini?

Untuk kesederhanaan, katakanlah selalu ada 20 gerakan setiap belokan dan untuk skenario terburuk kita selalu memilih yang terbesar, 19. Angka yang akan kita dapatkan adalah 19 ⋅ 20 m

+ 19 ⋅ 20 m-1 + 19 ⋅ 20 m-2 + ⋯ + 19 ⋅ 20 + 19 = 20 m + 1 - 1 di mana _m adalah jumlah gerakan. Untuk mengkodekan 20 m + 1 - 1 kita membutuhkan sekitar log 2 (20 m + 1 ) bit yang kira-kira (m + 1) ∗ log 2 (20) = 4,3219 ∗ (m + 1)

Rata-rata m = 80 (40 gerakan per pemain) sehingga ini akan membutuhkan 351 bit untuk dikodekan. Jika kami merekam banyak permainan, kami akan memerlukan pengodean universal karena kami tidak tahu berapa banyak bit yang dibutuhkan setiap angka

Kasus terburuk saat m = 400 (200 bergerak per pemain) jadi ini akan membutuhkan 1734 bit untuk dikodekan.

Perhatikan bahwa posisi yang ingin kita encode harus diberikan kepada kita melalui jalur terpendek untuk sampai ke sana dengan mengikuti aturan. Misalnya permainan berteori di sini tidak perlu m = 11741 untuk menyandikan posisi akhir. Alih-alih, kami menjalankan pencarian Breadth-First untuk menemukan jalur terpendek ke posisi itu dan menyandikannya. Saya tidak tahu seberapa dalam kita perlu menghitung semua posisi catur, tapi saya curiga 400 itu terlalu tinggi.

Perhitungan cepat:

Ada 12 buah unik atau kotak bisa kosong sehingga untuk menempatkannya di papan catur adalah 13 64 . Ini adalah perkiraan yang terlalu besar karena mencakup banyak posisi yang tidak valid. Ketika kita m bergerak ke dalam permainan yang telah kita buat sekitar 20 m posisi. Jadi kami mencari ketika 20 m = 13 64 . Log kedua sisi untuk mendapatkan m = 64 * log 20 (13) = 54.797. Ini menunjukkan bahwa kita harus dapat mencapai posisi apa pun dalam 55 gerakan.

Sekarang saya menghitung kasus terburuk menjadi m = 55 bukan m = 400, saya akan mengedit hasil saya. Untuk menyandikan posisi di mana m = 55 membutuhkan 243 bit. Saya juga akan mengatakan bahwa case rata-rata sekitar m = 40 yang membutuhkan 177 bit untuk dikodekan.

Jika kita menggunakan argumen amortisasi dari sebelumnya, kita mengkodekan 400 "papan catur" dalam 1734 bit sehingga kita mendapatkan bahwa setiap "papan catur" mengambil 4,335 bit dalam kasus terburuk.

Perhatikan bahwa g = 0 menunjukkan gim yang valid, gim di mana potongan pada kuadrat terendah bergerak ke kuadrat terendah.

Catatan tambahan:

Jika Anda ingin merujuk ke posisi tertentu dalam permainan, Anda mungkin perlu menyandikan indeks. Ini dapat ditambahkan baik secara manual misalnya menggabungkan indeks ke permainan, atau menambahkan gerakan "akhir" tambahan sebagai langkah terakhir yang mungkin dilakukan setiap belokan. Ini sekarang dapat menjelaskan kebobolan pemain, atau 2 berturut-turut untuk menunjukkan bahwa para pemain menyetujui pengundian. Ini hanya diperlukan jika permainan tidak berakhir dengan skakmat atau kebuntuan berdasarkan posisi, dalam hal ini tersirat. Dalam hal ini ia membawa jumlah bit yang dibutuhkan rata-rata menjadi 356 dan dalam kasus terburuk 1762.


1
Argumen "amortisasi" Anda tidak berfungsi. Tujuannya adalah untuk menyandikan papan yang diberikan oleh pengguna. Anda tidak bisa membagi biaya pengodean papan ini di antara 400 papan tambahan yang mungkin Anda hasilkan di sepanjang jalan. (Ini hanya akan baik-baik saja jika 400 papan itu diizinkan untuk dipilih secara independen oleh pengguna, dan tidak dibatasi oleh persyaratan untuk membentuk permainan catur.) Juga, permainan catur secara teoritis dapat mengambil ribuan gerakan , dan OP adalah jelas tentang tertarik pada kasus terburuk.
Anders Kaseorg

@AndersKaseorg: Sangat benar. Itu benar-benar tergantung pada tujuannya. Jika Anda mencoba untuk menyimpan seluruh permainan dengan semua algoritma lain, itu akan mengambil m * c byte di mana m adalah jumlah gerakan dan c adalah ukuran outputnya. Jadi jika Anda mencoba untuk menyimpan seluruh 80 langkah permainan menggunakan solusi 160 bit itu akan membutuhkan 12800 bit sedangkan milik saya hanya akan mengambil 351. Demi kompetisi saya mengakui bahwa Anda benar, tapi saya pikir itu adalah properti yang bagus untuk menunjukkan karena sangat umum untuk ingin menyimpan seluruh permainan dan bukan hanya papan.
edggy

Tujuannya tidak ambigu. “Tujuannya adalah untuk membuat representasi terkecil dari papan catur yang dapat digunakan (setelah diterjemahkan) untuk menentukan semua kemungkinan pergerakan pemain pada giliran itu. … Skor Anda ditentukan dalam skenario kasus terburuk - ukuran maksimum yang memungkinkan dalam bit. ”
Anders Kaseorg

@AndersKaseorg: Saya tidak pernah mengklaim itu ambigu. Saya hanya memutuskan untuk mengambil pendekatan yang berbeda. Satu hal yang perlu diperhatikan adalah untuk menemukan papan terkecil menggunakan algoritma saya, saya perlu jalur terkecil untuk sampai ke posisi ini. Misalnya dalam permainan belokan 11741 yang Anda tautkan untuk mendapatkan ke posisi papan yang sama, saya tidak perlu mengikuti jalur itu jika yang kita pedulikan hanyalah papan. Jadi untuk mengkodekan game tertaut saya hanya menemukan game terpendek yang tersisa dengan 2 raja di kotak yang mungkin hanya 200 putaran atau kurang. Ini dapat dilakukan dengan pencarian mendalam-pertama.
edggy

Menggunakan permainan setara yang lebih pendek tidak masalah, jika Anda benar-benar dapat membuktikan bahwa setiap posisi dapat dicapai dalam 200 putaran atau kurang (sekarang ini sepertinya hanya tebakan). Anda juga harus memperhitungkan posisi catur dengan lebih dari 100 gerakan hukum , kecuali Anda dapat membuktikan bahwa itu tidak muncul dalam konstruksi Anda. Membagi hasil Anda dengan jumlah gerakan dalam permainan masih tidak diizinkan oleh aturan tantangan ini.
Anders Kaseorg
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.