Найменше стиснення шахової дошки


39

Напишіть алгоритм чи програму, яка може кодувати та розшифровувати шахову дошку. Мета полягає в тому, щоб зробити найменше представлення шахової дошки, яку можна було б використати (колись розшифрувати), щоб визначити всі можливості руху гравця на цьому кроці.

Кодування повинно бути в змозі показати:

  • Чия це черга.
  • Чи може гравець замок з кожного боку.
  • Чи може гравець виконувати ансамблю, і якщо так, то який із пішаків?
  • Позиції всіх штук.

Важлива примітка щодо закидання: Якщо білі рухають свого короля на один оборот, а потім переміщують його назад на наступний, повинно бути зрозуміло, що вони не зможуть замок з обох боків після цього. Те ж саме пішло б, якби вони рухали лівою чи правою гракою. Хоча дошка візуально знаходиться в тому ж стані, що і два витки тому, стан гри змінився. Більше інформації тут: http://en.wikipedia.org/wiki/Chess#Castling

Важлива примітка про ен-пасант: Це також поворотний рух. Прочитайте правила для отримання додаткової інформації. http://en.wikipedia.org/wiki/Chess#En_passant

Визначте вхід та вихід за потребою. Основні реквізити для тих, хто може це стиснути найбільше!

Ваш результат визначається в гіршому випадку - максимально можливий розмір у бітах. Обов’язково покажіть, як ви обчислили це число і що ви рахували. Стріляйте за найменшого найгіршого випадку!


Що ви маєте на увазі під "побітним"?
Пітер Тейлор

Це найменший код або найбільш стислий? Більш стиснене цікавіше.
Джастін

Вибачте, що не уточнили. Побітове значення в тому сенсі, що ви можете стиснути його лише в тому випадку, якщо ви почнете представляти його як біти, що вимагатиме певної побітової операції. Погане використання з мого боку. Також найбільш стислий, не найменший код.
Seltzer


1
@AJMansfield, що може бути корисним для дощок з приблизно 28 чоловіками, але я підрахував, що 117 біт є достатньо для дощок з усіма 32 чоловіками, що приблизно на 50 біт менше, ніж цільовий. Ускладнення полягає в тому, що, коли ви перейдете нижче 32 чоловіки, підвищення кваліфікації може дати гравцю більше єпископів.
Пітер Тейлор

Відповіді:


27

Мінімальна: 12 біт
Макс .:
Сер .:

Вчора ввечері думав, що я міг би зробити його ще меншим.

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)

Результат - вражаючий розмір у 12 біт !

То як щодо K +1 інший тип твору?

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

Там можливе 2 розташування під дерева.

   /\      /\
  +  K    K  +

Обидва отримують однакові розміри бітів для всіх штук. Тож не важливо, до чого ми користуємось, я оберу перший.

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

Так що на King +2 інші типи штук

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

Існує 5 можливих під дерев (я використаю 1 і 2, щоб вказати, який з фрагментів.)

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

Таким чином, нам буде потрібно 3 біта, щоб кодувати, яке під дерево використовувати.

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

Ще роблю аналіз на більшу частину

+3 Інше

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

+4 Інше

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

+5 Інше

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

Макс: 208?


Чи можливо кодувати всі ці піддерева на 9 біт?

Якщо ми підсумовуємо всі можливі піддерева, ми отримуємо 392 можливих під деревця.

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

Використання Freq ID

З тих пір 164603 унікальних частотних частот .

Log2( 164603) = 17.3286110452
             ~ 18 bits

0
 0000 0000 0000 0000 00  Freq ID

(+000) (+00) Кастинг

Макс: = 204 біта


rev 3

Мінімальна: 82 Макс.: 199 Сер.: 160

Нарешті обійшлося зробити аналіз, щоб знайти максимальний розмір бітів. З оптимальним кодуванням huffman для кожної унікальної частоти .

               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 

Зауважте, що це найгірший можливий розмір, який стовпець стовпця En-Passant, якщо кількість пішаків більша за одиницю. Незалежно від кольорів та положення пішаків, певна дошка може бути на 3 біти меншою.

Також є лише 144 різних розмірів (найгірший випадок) для розміру дошки.


75 - 216 біт (v2) v1 Мінімальний розмір - 98 біт (12,25 байт), тільки два царі на платі.

Максимальний розмір - лише 216 біт (27 байт.):

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

В середньому розмір буде приблизно 157 біт (19.625 байт).

Шматки

Для кодування плати я використовую схему кодування двійкового дерева. Порожній квадрат є найчастішим з усіх, де є між 32 і 62 виступи. Далі - пішаки, потім Граки, Лицарі, Єпископи і найменш часті - Королева та Король.

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

Початкову плату можна кодувати всього в 166 біт (20,75 байт)

  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

Щоб вказати, хто рухається, потрібен лише один біт

0-> Black , 1-> White

У ролях можна кодувати 4 біти.

 B  W
LR LR
00 00

Тому я використовую 171 біт (21,375 байт)

En-Passe можна закодувати лише в 16 біт (2 байти)

Так що загалом це 187 біт (23,375 байт).

Макет

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

Ще не написано жодного коду.

Зауважте, що 3 біта, які не використовуються. Так що макс - 213 біт .


Можливі вдосконалення

1) Зменшено форму заголовка блоку на 24 до 8 біт (із пропозицією @Peter Taylor)

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

2) Заголовок змінної довжини

Невеликий 4-бітний фіксований заголовок

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

Наступний блок додаткових біт (якщо виведення все ще можливо)

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

Наступний блок додаткових біт (якщо пішаки є)

000--> En-Passant column Position

Тож тепер у мене заголовок змінної довжини 4 - 11 біт


3) Використовуйте іншу схему кодування залежно від того, які шматки залишилися на дошці.

Змінюючи кодування дерева в залежності від того, які шматки є на дошці та частоти.

Одне можливе кодування для кінця гри (без пішаків)

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

Це приблизно ~ 4 біта за штуку.

Який тип творів присутній на дошці?

RBNQK Permutation
11111 (11111)

Перестановка - змінна довжина 0-5 біт. Якщо залишився лише один тип шматка, не включайте його.

Яку перестановку цих частин використовувати для дерева? Це фактична кількість штук у наведеному вище прикладі, це 5 штук, тому 120 можливих перестановок, які можна закодувати.

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

Пам'ятайте, що для порожніх квадратів та кольору є біти додавання.


Приклади

Наведемо приклад лише QK, що залишився

RBNKQ
00011

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

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

0000 00011 Header ==> 9 bits

81 біт загалом


Наведемо та приклад лише залишилися королів

 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

Покладіть всі разом

 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

Тому я обчислюю найменше кодування для плати на 75 біт (9 біт 3 біт)

Поки ще не слід обчислити, як ця схема кодування впливає на максимальний розмір.


Вдосконалення 4

Зменшіть кількість біт для закидання до лише 2 біт. Просто кастинг для гравця, який це черга.

 0 Castling possible (from header block)
 LR 
 00

Думаючи про це, можливо, краще просто включити 2 біти всередину заголовкового блоку.


Вам не потрібно 16 біт для пасажира. Найбільше один пішак перемістився в останню чергу, тому вистачає чотирьох бітів (наприклад, 1111для "не можливий перехід" або стовпець як двійкове число в іншому випадку).
Пітер Тейлор

Чому пішаки отримують кращу позицію на дереві? У загальному випадку вони найбільш поширені, але в крайньому випадку R / B / N можуть з'являтися в 10 разів.
ugoren

@PeterTaylor, насправді 3 біта вистачає для проходження. Якщо ви порахуєте лише стовпці з чорною пішаком 5-го рангу (якщо припустити білий хід), 8 стає недійсним.
ugoren

1
Зауважте, що ваш найгірший випадок насправді неможливий. Промоція неможлива без захоплення (потрібно хоча б одне захоплення на 2 акції).
угорен

2
Зауважте, що для кодування 64 позицій (для білого або чорного короля) вам потрібно 6 біт (2 ** 6 = 64).
lambruscoAcido

17

192 біта (найгірший випадок)

Ось дуже проста схема зберігання, яка повинна справлятися з умовними рекламними пропозиціями пішаків, і ніколи не потребує більше 64 + 4 × 32 = 192 біт:

  • Перші 64 біти зберігають бітборд, який повідомляє, де знаходяться шматки (але не те, що вони є). Тобто, ми зберігаємо по одному біту на кожен квадрат шахової дошки (починаючи з квадрата a1, потім b1, c1 і т. Д. До квадрата h8) таким чином, що вільний квадрат представлений 0, а зайнятий квадрат - 1.

  • Далі, для кожного з квадратів, позначених як зайняті на бітборді, ми зберігаємо 4-розрядний кусок, що кодує фрагмент на цьому квадраті. Перший з чотирьох бітів кодує колір шматка (0 = білий, 1 = чорний), а інші три біти кодують тип шматка:

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

    Тип шматка

    0 = (нормальна) пішака
    1 = (нормальна) ладья
    2 = лицар
    3 = єпископ
    4 = королева
    5 = король (гравця, щоб рухатись далі)
    6 = цар (іншого гравця)

    Зверніть увагу на два кодування для короля, які використовуються для визначення того, на яку чергу гравець рухається. (Насправді, оскільки на дошці завжди є два королі, які дозволяють використовувати чотири комбінації кодів 5 і 6, ми можемо досить легко кодувати другий біт інформації.)

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

    Для кодування додаткової інформації, необхідної для правил проходження пасажирів та викидів, ми вводимо один додатковий тип шматка, який позначає пішак або грак залежно від рядка, на якому він відображається:

    7 (на рядах 1 і 8) = грак, який ніколи не рухався і чий король також ніколи не переміщався, і тому придатний для закидання
    7 (у рядках 4 і 5) = пішак, який тільки що просунув два квадрати, і тому можуть бути захоплені пасажиром

Збираємо все це разом:

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

Таким чином, загальна кількість біт, необхідних для кодування стану плати, становить 64 + 4 × # штук на борту. Оскільки на платі ніколи не може бути більше 32 штук, максимальна довжина цього кодування - 192 біта.

Наприклад, використовуючи описане вище кодування, початковий стан плати кодується як (пробіл, вставлений для читабельності):

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

або, у шістнадцятковій кількості:

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

2
"пішак, який нещодавно просунув два квадрати" та "грак, який ніколи не переміщався", може поділяти один і той же проміжок стану, оскільки вони взаємно виключають залежно від рядка, на якому вони перебувають. Додатковий вільний стан може бути використаний для кодування "короля кольору, чия черга його"; ви повинні таким чином позбутися звисаючого шматочка.
FireFly

Ви також можете трохи заощадити, зберігаючи лише 63 біти для бітборда та виводячи останній біт із кількості закодованих чоловіків. (Мені не зрозуміло, чи це обман чи ні, тому що це вимагає зовнішнього кодування довжини бітової послідовності). І якщо ви скинете штати 6 і 7 для чоловіків, вам потрібно кодувати до 6 ^ 32, що займає 82,7 біт; закруглюючи до 83, це економить 13 біт на використанні станів 6 і 7, і ви можете кодувати цю інформацію лише у 8 біт.
Пітер Тейлор

Дякую, @FireFly! Я реалізував вашу пропозицію. (Пропозиція Пітера Тейлора, звичайно, ще ефективніша, але я до цього часу не використовував її, тому що мені подобається просте бінарне кодування поточної схеми. Ви завжди можете подати її як окремий запис ...)
Ільмарі Каронен

Гаразд - це м'яко складне. Але вислухай мене. Якщо ви просто приймете 1 біт-хіт на покажчику повороту, ви можете замінити короля повороту на шматок, який я називаю пішаком1. Змініть пішака на пішак0. Тепер, коли є пішак (не на вразливих пасажирів), ви також отримуєте один біт інформації про наступний фрагмент (або 0 для пішака0, або 1 для пішака1). Оскільки 16 пішаків, ви отримуєте на 16 біт менше 1 для індикатора повороту. Щоразу, коли пішак, вразливий для пасажирів, вам доведеться додати один біт назад після нього. Але оскільки прохід має відбутися негайно, ваш мінімальний приріст - 14 біт.
користувач5957401

Ви також можете зробити подібну справу з чимось на зразок єпископів. Припустимо, що у вас єпископ не в його «спеціальній зоні» (10 плям у його кутах та центральний ряд на його стороні) позначені як особливі. Тому що ви знаєте його місцезнаходження - ви знаєте її єпископа. Зараз у вас є два єпископи, і кожен із них може дати 0 або 1 на наступному творі. Це дає ще 4 біти - але найгірший випадок є єпископами у всіх спеціальних зонах, і жодних вигод.
користувач5957401

14

160 біт найгірший випадок

Опублікувавши свою попередню відповідь 22 байти, я почав задаватися питанням, чи зможемо ми опуститися до 21 байта. Однак коли я побачив дивовижні 166 байт Пітера Тейлора, я подумав: "Почекай, схоже, п'ять 32-розрядних слів можуть бути можливими!"

Отож, після дуже багато роздумів, я придумав таке: 159.91936391 байт (досить щільний вміст!) Цей рівень стиснення потребує досить складної програми, але я подумав, як змусити його запуститись у розумний час.

Це буде довгим повідомленням, тому, будь ласка, візьміть мене зі мною, я опублікую те, що можу сьогодні, і незабаром додаю кілька біт коду.

Отже, ось як це зробити:

En Passant та брошура кодуються незаконними позиціями (0 біт)

En Passant

Як згадується в інших відповідях, існує максимум 5 можливих квадратів, на яких пішак, вразливий для пасажира, може стояти. Це квадрати поруч із пішаками гравця, чия черга.

Для кодування цього пішака, вразливого для пасажира, обмінюється тим, що знаходиться на одному з квадратів у першому чи останньому ряду. Це може бути або людина, або порожній квадрат. Це створює незаконне становище, оскільки пішаки не можуть бути в цих рядах. Декодер повинен повернути пішака в правильне положення, витягуючи обхідну інформацію.

Для того, щоб це не заважало кодуванню бродіння, важливо, щоб квадрати, на яких стоять королі на початку гри, не були порушені, і щоб процедура кодування, що склалася, не розміщувала царів поруч, що було б незаконним становищем короля. Для задоволення другої з цих точок кодер має два варіанти, на який квадрат він обміняє прохідну пішаку. Квадрат першого вибору для кожної з до 5 пішаків - A8, B8, C8, G8, H8. Другий вибір: A1, B1, C1, G1, H1.

Кастинг

Король, якому дозволено замок, знаходиться за визначенням, як і раніше на своїй початковій площі. З білим королем на його початковій площі є всього 63 квадрата, де чорний король може стояти, 58 з яких є законними (йому не дозволяється рухатися прямо біля білого короля, оскільки він поставив би себе під контроль). Якщо білому королю дозволено замок, йому або дозволяється замок лівим граком, правою граком, або обома. Таким чином, існує 3x58 = 174 можливості, коли білий король може замок, ще 174, де чорний король може замок, і ще 3x3 = 9, де обидва можуть замок, загалом 357.

Є 420 незаконних домовленостей двох королів, де вони знаходяться на сусідніх квадратах: 3x4 = 12, коли білий король знаходиться в куті, 5x24 = 120, коли він знаходиться на краю, і 8x36 = 288, коли він знаходиться на іншій площі. Тому легко є достатньо незаконних позицій для кодування всіх можливих можливостей ролі.

Якщо хоча б одному королю дозволено замок, енкодер шукає дані про вивільнення та позиційні дані тих царів, яким не дозволяється замовляти таблицю (або, як варіант, використовувати алгоритм, який я тут не вказуватиму) та створити незаконне положення двох царів. Потім він обмінявся б царями з тим, що сталося на цих площах.

Важливо, щоб це було закодовано після та розшифроване перед перехідним, інакше можливі певні перешкоди.

Порівняння

Отже, поки що я не використовував жодних бітів! Дивлячись на відповідь Петра, у мене ще є таке кодування:

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

Це найгірший випадок із 29 чоловіків (див. Відповідь Петра.) Нижче я покажу, як я домігся граничного покращення (принаймні для випадку 29 чоловіків) в обох пунктах, позначених у **.

Які площі зайняті / чия черга?

Найпростіший спосіб кодування квадратів, зайнятих, - це 64-бітна сітка. Це також говорить нам, скільки площ зайнято. Однак це дещо марно, оскільки там не можна зайняти більше 32 квадратів. Моє рішення - використовувати 1 для кодування для зайнятих квадратів, коли настає черга Уайта, а 0 - для кодування для зайнятих квадратів, коли це черга Чорного. Зараз використовуються всі комбінації, а відходів немає.

Таким чином ми економимо на трохи для зберігання черги: менше 32 1-х, це черга білого, більше 32 1-х, це черга чорного. Єдиний неоднозначний випадок, коли всі чоловіки на дошці, а там 32 1 та 32 0. Тому додатковий біт потрібен лише для цього випадку. Оскільки рекламних акцій не може бути, поки не відбулося захоплення, цей додатковий біт не впливає на найгірший випадок у цілому (який трапляється з 3 чоловіками, захопленими та 29, що залишилися.)

Колір чоловіків, що займають площі

З вищесказаного ми знаємо, скільки є чоловіків. Наступний витяг трикутника Паскаля розповідає, скільки можливостей для різних розподілів чорного та білого кольорів. Наприклад, для 3-х чоловіків можливі такі: 3 чорні чоловіки (1 перестановка) 2 чорні, 1 білі, (3 перестановки), 1 чорні, 2 білі (3 перестановки), 3 білі (1 перестановка.) Загальна 2 3 = 8. Загалом, для меншої кількості чоловіків існує 2 n можливостей. Однак усі можливості чорного та білого кольору є незаконними (принаймні, король кожної сторони повинен бути на дошці), тому фактична кількість легальних перестановок становить 2 n -2 (ігноруйте 1 у трикутнику Паскаля.)

Для більш ніж 16 чоловіків загалом існує додаткове обмеження в тому, що на дошці може бути не більше 16 чоловіків кожного кольору. Тому, коли всі 32 чоловіки на борту, їх повинно бути 16, а загальна кількість можливостей - 601080390, що зовсім менше 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

Кількість можливостей можна знайти, підсумовуючи "рядки" цього витягу трикутника паскалів (під якими я маю на увазі діагоналі NE-SW таблиці, оскільки я повернув трикутник на 45 градусів проти годинникової стрілки для зручного подання. Кількість потрібних біт Отже, для кодування повороту, зайнятих квадратів та кольорів чоловіків слід таким чином:

До 25 чоловіків: трохи менше 64+ (кількість чоловіків)
Більше 25 чоловіків:

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

Для двох кольорів, які чоловіки та в якому порядку?

Як і в попередніх відповідях, жодні пішаки не можна просувати, поки не відбудеться захоплення, оскільки кожна піша блокована пішаком протилежного кольору в одному стовпчику. Відповідь Петра вважала (як верхню межу), що кожне захоплення може призвести до одного просування за сторону, яку захоплюють, і двох для захоплення сторони. Однак ми можемо розділити це на кілька випадків:

  1. Чорний пішак захоплює білий пішак: тепер пішак, що захоплює, вільний для просування, оскільки він зараз знаходиться в іншій колонці. Його колега в цій же колонці також може просувати. Чорний пішак на оригінальній колонці білого пішака також може просувати. Це єдиний випадок, який дозволяє 3 акції.

  2. Чорний пішак проходить повз білого пішака на сусідній колоні, а потім захоплює білий шматок (крім пішака) позаду. Це дає змогу захоплювати пішака та білого пішака, який знаходився на початковій колонці. По одній акції для кожної сторони.

  3. Білий пішак захоплюється по шматках (крім пішаків.) Це, як правило, дозволяє просувати одну рекламу лише для Чорних. Єдиний виняток - це звільнення блокованого пішака, яке вже було викликано кількома захопленнями пішаків пішаків на один і той же стовпчик.

Отже, в якості базового випадку ми можемо вважати, що кожен захоплення дозволяє по одній рекламі для кожної сторони. У випадку, якщо чоловік, що потрапив у полон, - пішак, може бути додаткова промоція для боку, що захоплює.

Я написав програму, схожу на пітерську. Це дещо суворіше, але воно має важливе доповнення: він може обчислити кількість можливих перестановок, коли гравець починає менше, ніж звичайні 8 пішаків. Ось деякі дані, отримані програмою:

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

Ми можемо бачити, що для такого випадку, як 8 пішаків, 15 чоловіків, 0 заохочень, кількість перестановок лише трохи менше, ніж для 8 пішаків у 16 ​​чоловіків, 0 заохочень. Однак якщо ми розглянемо такий випадок, як 7 пішаків, 15 чоловіків, 0 заохочень (це те саме, що вважати, що чоловік, що потрапив у полон, був певною пешкою), ми отримуємо приблизно половину кількості перестановок.

Отже, для випадку, коли у Чорного є 16 чоловіків, а у білого - 15 чоловіків, ми можемо розглянути верхню оцінку 2 рекламних акцій для Чорного та однієї реклами для Білих:

5383778400 x 660810150 = 3.55766E+18 possibilities

Однак ми можемо зробити краще, якщо діяти наступним чином.

А. Розгляньте одну рекламну акцію для чорно-білих, припускаючи, що людина, яку Білий програв, може бути будь-якого типу:

843242400 x 660810150 = 5.57223E+17 possibilities

В. Розгляньте додаткові можливості для Чорного, якщо він має дві рекламні акції, помножені на лише ті можливості для білих, у яких він втратив пішака.

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

Якщо скласти ці два разом, ми отримаємо 2.25072E + 18, що є меншим числом, ніж 3.55766E + 18. Нижче перераховані всі можливості для до 3 захоплених (29 чоловіків).

(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

Тож для найгіршого випадку однієї сторони з 15 чоловіками, а іншої з 14 чоловіками, нам потрібно 67.804 біта.

Додавши це до 92.116 біт, необхідних для вказівки квадратів і якого кольору, ми отримаємо загалом 67.804 + 92.116 = 159.92 біт.


1
Величезне спасибі @Einacio за те, що змінив мої десяткові коми після десяткових знаків. Я робив багато своїх таблиць в Excel на іспанському комп’ютері, і розміщення цього завдання було великою роботою, тому виправити це було щось, що я залишив на потім. Як я кажу, я ще не закінчив цю посаду, я додам свою програму підрахунку перестановки та деякі фрагменти коду про кодування / декодування, коли встигну. PS. Я поняття не мав, тому багато людей читали це :-)
Level River St,

врешті-решт, вам вдалося взяти байти замість бітів, що саме ви мали на увазі, що може спричинити читача
чиффузію

13

177 біт найгірший випадок

Цей алгоритм, хоч і важко простий, дає найгірший випадок 177 біт (на практиці 184b = 23B), найкращий сценарій - 13b (16b = 2B), коли залишилося лише 2 королі.

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

Дуже хороша. Ви можете зробити це ще більш ефективним, замінивши біти 14-105 (92 біта) кодуванням на основі мультиноміальних коефіцієнтів. sum_{i=0}^{15} sum_{j=0}^{15} 62! / (i! j! (62-i-j)!) < 2^87.45.
Пітер Тейлор

Єдине, що я хотів би змінити - це створити досить більш спрощену версію для обширної області. Наприклад: якщо ви кодуєте 30 частин в базі 5, і є максимум 5 обхідних положень, то ви можете мати 5 ^ 31 <2 ^ 72. Те саме, як якщо б ви розділили їх на безперервний (13) і не обхідний (59), але без зайвої складності.
Алін Стоян

Це фактично використовує 1 додатковий біт. Причина полягає в тому, що може (в гіршому випадку) бути 5 обширних можливостей, але мені все одно потрібно заявити про можливість "без обходу", тобто для 6-го стану. 1 додатковий біт в цьому випадку перейде до оголошення обхідного можливим чи ні (і при такому підході я міг би також використати ще простіший підхід з кодуванням 30 частин, пропускаючи обхідний блок, і використовувати 3 біти окремо для обхідної перевірки, що б також призводять до використання +1 біт). Наступний 5-й ряд дозволить 5 потенційним обходам (черга Уайта): BWBBWBBW
FIQ

так, ви праві.
Алін Стоян

7

166 біт

  • 1 біт: чия черга?
  • 2біти: які варіанти лиття відкриті? (Зауважте, що при уважному читанні цього питання потрібно лише записати варіанти відбору для гравця, чия черга це відбувається).
  • lg 6 ~= 2.585біти: які варіанти пропускання відкриті? (Дивіться мою іншу відповідь)
  • lg sum_{i=1}^{16} sum_{j=1}^{16} 64! / (i! j! (64-i-j)! = lg 3629590441720924477681996172 ~= 91.552 біти: які квадрати займають чоловіки якого кольору?
  • У гіршому випадку, lg 451366131803622235200 ~= 68.613щоб вказати чоловіків і в якому порядку (див. Нижче)

Використовуючи арифметичне кодування (оскільки на кожному кроці ми застосовуємо рівномірний розподіл) ми можемо досягти ceil(3 + 2.585 + 91.552 + 68.613) = 166бітів.

Кодування для чоловіків: враховуючи, що ми знаємо, скільки чоловіків даного кольору є, ми можемо легко перерахувати всі можливі розподіли / мультисети чоловіків (наприклад, з 5 чоловіками у нас може бути один король, одна королева, два граки і Пішак), і тоді ми можемо розглянути всі можливі перестановки кожного розподілу.

Однак ми можемо зробити ще краще, враховуючи взаємозалежності. Я роблю це лише на дуже базовому рівні: скільки можливих акцій? Пішак може стати "пройденим" і здатний просуватися трьома способами: він захоплює і так переміщується в інший стовпчик; або його протилежний пішак захоплює і так переміщується в інший стовпчик; або його захоплений пішак захоплений. Таким чином, захоплення для білого потенційно створює дві пішачні пішаки для білого та одну для чорної.

Ми можемо створити часткову таблицю верхніх меж на акціях:

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

Ми також можемо обчислити кількість перестановок, враховуючи, що у гравця є Nчоловіки і не більше ніж Pпешені пішаки:

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

Поєднавши ці два, ми можемо отримати кількість бітів, необхідних для визначення обох перестановок, враховуючи кількість чоловіків з обох сторін:

           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

Якщо це не в цьому розділі таблиці, ми можемо просто припустити, що обидві сторони мають до 8 рекламних акцій, і ми все ще робимо краще, ніж найгірший випадок, який становить 68.613 біт, коли в одного 14 чоловіків, а в другому 15 чоловіків.

Зауважте, що це ще довгий шлях від ідеального представництва, оскільки це дозволяє безліч незаконних посад.

Код для обчислення таблиці перестановки:

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

    }
}

Як виводите посади королів? Ви використовуєте 15 чоловіків у своїх обчисленнях і жодних спеціальних бітів для позицій короля.
Алін Стоян

@AlinStoian, ой. Я мав <радше, ніж <=у виходному циклі своєї програми. Дякуємо, що вказали на це. Я все-таки міг відновити попередній бал, будучи спеціальним корпусом всіх 32 чоловіків, які перебувають на дошці, але зараз цього робити не буду.
Пітер Тейлор

Цікаві дані! Найгірший теоретичний випадок із захопленими 3 чоловіками
рівень річки Св.

@steveverrill, що я дуже хотів би зробити, це кодувати позиції пішаків і кількість рекламних пропозицій в одному "блоці", а потім позиції та значення частини. Однак є щонайменше 2 ^ 38 позиції пішаків, не беручи до уваги рекламні акції, і перерахування їх ефективно поки що уникнуло мене.
Пітер Тейлор

@petertaylor Якщо у вас на дошці лише 16 пішаків, обмежених 48 квадратами, у вас є 48! / 32! / 8! / 8! = 29019905518636890 можливостей. Трохи більше 2 ^ 54! З них деякі є незаконними, ви не можете мати всіх пішаків одного кольору на одній стороні дошки.
Рівень річки Св.

5

178 біт (174 на дрібку!) Найгірший випадок

Привіт, я просто повернувся до кодування, чого я ще не робив з коледжу. Я побачив цей сайт і подумав, що це виглядає цікаво. Я зробив невелику теоретичну перевірку, і, здається, потрібно щонайменше 146 біт для досконалого алгоритму, напевно, ще трохи (я поясню в коментарях, коли в мене є момент).

Так чи інакше, я структурую дані. Основна концепція входить у 178 біт, але за допомогою деякого джиггери покеру вона може бути знижена до 174 (це 21 3/4 байт). 175 легше програмувати, легше читати людину і все ще знаходиться в межах 22 байтів.

А) Положення обох королів: по 6 біт для кожного з білих і чорних 12 BITS

Б) З решти 62 квадратів, які зайняті? Матриця з 62 BITS

В) Чия черга? 1 БІТ

ВСЕ ТАКОЖ: 75 біт

Г) En Passant. Якщо черга білого рухається, до 5 чорних пішаків можуть виглядати так, ніби вони можуть бути захоплені En Passant. Чорна пішак повинна знаходитись у рядку 5 (знизу вгору, починаючи з нуля), а біля неї - білий пішак. Одна ситуація з максимальною кількістю можливих захоплень виглядає приблизно так:

BWBBWBBW

Якби в 5 ряду було 6 чорних пішаків, білі мали б лише 2 квадрати і могли загрожувати лише 4 чорним пішакам, тому не можна мати більше 5 чорних пішаків, очевидно, під загрозою з боку En Pasant. Тому нам знадобиться число від 1 до 5, яке вказує, яка з (до 5) пішаків у рядку 5, яка має ворожу (в даному випадку білу) пішаку поруч, була просунута 2 квадрати в останню чергу ( або нуль, якщо пішака немає в цій ситуації таким чином перемістився в останню чергу.)

E) Що стосується до 30 зайнятих квадратів (не включаючи царів), що вони містять?

Є 10 можливостей, кожна представлена ​​десятковим числом.

Найменш значущий біт представляє колір.

Отже, парні числа білі, непарні числа - чорні.

Білий / Чорний

Пішак 0/1 (або Лад, якому дозволено замок *)

Лицар 2/3

Єпископ 4/5

Грач 6/7

Королева 8/9

* Грак, якому дозволено замок (і тому ніколи не переміщувався з першого чи останнього ряду) представлений 0 або 1 замість 6 або 7. Його не можна переплутати з пішаком, оскільки пішаків не можна знайти на першому або останній ряд.

Це дає десяткове число до 30 цифр, яке ми можемо помножити на 6, а потім додати код для En passant. Отримане число поміститься в 103 біти, що при додаванні до 75 згаданих вище становить 103 + 75 = 178 біт . Насправді, якщо ми просто помножимо на 10 замість 6, це не має ніякої різниці в кількості використаних бітів, і розшифрувати простіше.

Це всього на 2 біти більше 22 байтів. Однак ми можемо натиснути на 174 біт, як пояснено нижче.

Якщо жоден шматок не був захоплений, тоді просування пішака неможливо .

Доказ такий. Уявіть, що білі одержимі просуванням пішака (наприклад) у стовпці Е, з самого початку гри. Навпроти цього пішака стоїть чорна пішака. Тому для просування цього пішака має відбутися одне з наступних:

1) Чорний пішак захоплений.

2) Чорна пішака захоплює інший шматок і тому рухається з шляху.

3) білий пішак захоплює пішака на сусідньому стовпчику, такому як стовпець D.

4) білий пішак проходить (або проходить повз нього) чорну пішаку на сусідній колоні, а потім захоплює шматок у тому ж сусідньому стовпчику, внаслідок чого білий пішак змінює стовпчик.

Випадок 4 є найцікавішим, оскільки чіткий шлях до просування має не лише біла пішачка, яка почалася на колонці Е. Чорний пішак на стовпчику, що залишається на колонці Е, також може просувати. Тому одне захоплення може прояснити шлях для просування пешків кожного кольору.

У будь-якому випадку, той факт, що жодна пішака не може просуватись до захоплення шматка, означає, що нам не доведеться зберігати 30-ту частину. Ми можемо розробити це шляхом усунення (або віднімання, оскільки повний набір шматочкових кодів на початку гри завжди додає однакову суму = 80.) Одним незначним моментом є те, що ми повинні гарантувати, що квадрати, де грають Стенди на початку гри є одними з перших сканованих (бо якби вони були останніми, ми б не знали, чи грак може замок чи ні.) Це легко зробити, скануючи рядок 0, а потім рядки 7 до 1: Для r = 8 - 1 рядок сканування [r mod 8].

Отже, матриця бітів у (B) підкаже нам, скільки є шматочків (виключаючи царів.) Якщо їх цілих 30, ігноруйте останній фрагмент при кодуванні, декодер розробить, що це було. Тепер у нас є до 29-значного десяткового числа, яке множимо на 6 і додаємо до коду En Passant. Отримане число просто видавиться на 99 біт, даючи в цілому 99 + 75 = 174 біт.

Як приклад Ось фактична позиція. Білий щойно здійснив свій перший крок (піша підопічного короля), і настала черга Чорного.

rnbqkbnr
pppppppp


    P

PPPP PPP
RNBQKBNR

А) Положення королів (Біле / Чорне в восьмериці, 12 біт ): 03 73 = 000011 111011

Б) Які квадрати зайняті? Почніть з нуля рядка (нижній ряд), потім усі інші рядки зверху вниз, пропускаючи королів:

1111 111

1111 111
11111111
00000000
00000000
00001000
00000000
11110111 

В) Черг Чорного: Поверніть біт = 1

Г) En Passant. Поруч з чорною пішаком немає білого пішака, тому немає пішака, яку можна було б взяти за пасею (навіть якщо цей пішак просунувся в останній хід), тому D = 0. Якщо, замість того, щоб розглядати лише пішаків, які мають вороже пішака біля них, ми вважаємо всі пішаки, які не мають дружніх шматочків біля них з обох сторін, то D було б 1, оскільки в цій ситуації є одна така піша, і саме ця пішак справді був зворушений в останню чергу.

E) Знову спочатку нижній ряд, потім усі інші ряди зверху вниз, пропускаючи королів, і чотири нерозбірливі граки, які позначаються як 0 або 1 (номери, зазвичай зарезервовані для пішаків.)

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

30-ту цифру (в дужках) можна відкинути.

Хоча це і не дуже очевидно, пішак, який Білий просунувся, насправді знаходиться на одному кінці списку пішаків, оскільки ми скануємо рядок за рядком.

Наші дані тепер виглядають так, з 29 кодами на вміст квадратів плюс код En Passant:

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

Найкраще сканувати справа наліво при розшифровці та зліва направо (зворотний порядок) при кодуванні. Це означає, що коли буде менше штук, ми матимемо меншу кількість, зберігаючи максимальну узгодженість (тобто ми хочемо, щоб порожній простір / нулі були провідними, а не відстаючими, щоб увімкнути стискання малозайнятих дощок.) Коли у нас є лише 2 королі на платі ми матимемо зазначені вище 75 біт плюс 3 біти для зберігання en passant data = 78 біт у кращому випадку. Кожен додатковий шматок має трохи менше 3,5 біт (2 штуки можна зберігати в 7 біт, тому що 100 <128.)

Практична проблема полягає в тому, що 99-бітове ціле число занадто велике, щоб вмістити 64-бітну цілочисленну змінну, що означає, що багато мов програмування не забезпечують його підтримку (ви не можете просто конвертувати рядкове представлення 29-30 цифр число на ціле число.) Як простий спосіб кодування для 22 байтів, ми можемо розбити 30-значний номер (29 штук коду + en прохідний код) на два 15-значні числа, кожне з яких вміститься по 50 біт кожен (всього 100 біт плюс 75 згаданих вище становить 175 біт у найгіршому випадку.)

Для максимального стиснення, як зазначено вище, 29 десяткових цифр плюс код En Passant (6 можливих значень) буде приблизно вписуватися в 99 біт (загалом 174 біт), але без підтримки мови для цілих чисел такого розміру це складно програмувати. Можливо, буде простіше відокремити 29 кольорових бітів і працювати з кодами типу штук (5 можливостей) та кодом En passant (6 можливостей) окремо від кольорів (70 біт, майже вписується в 64-бітну змінну.)


Гарний трюк з останнім чоловіком.
Пітер Тейлор

5

Ось повне рішення, фактично гірший 181 біт

У центрі уваги - проста програма, яку ви легко зрозумієте

Введення FEN, тут відкриття, воно має шість полів (5 і 6 проігноровано):

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

Перше поле (розміщення шматка) розбирається

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

Виробляти:

rnbqkbnrpppppppp________________________________PPPPPPPPRNBQKBNR

Поле перше: кодуйте розташування королів (12 біт):

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

Поле друге: кодуйте фрагменти (до 5 біт на шматок):

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

Поле третє: активний колір (1 біт)

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

Поле четверте: доступність викидання (4 біти)

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

П'яте поле: en passant (нуль або 3 біта)

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

Найгірший варіант - 200 біт

  • Розміщення двох королів - 12 біт
  • Правління
    • QRRBBNN QQQQQQQQ - 75 біт
    • qrrbbnn qqqqqqqq - 75 біт
    • Порожні квадрати - 30 біт
  • Активний колір - 1 біт
  • Кастинг - 4 біти
  • En Passant - 3 біти

Фактично найгірший випадок

Кожен гравець не може просувати всі пішаки, не захоплюючи інших фігур . Ось ефект ентропії захоплення шматка:

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

Тож насправді найгірша рада:

  • QRRBBNN QQQQQQQQ - 75 біт
  • qrrbbnn qqqq - 55 біт
  • Порожні квадрати - 34 біти

Найгірший випадок - це рекламувати всі твори, а не залишати пішаків на проході.

РОЗПОЛОЖЕННЯ АКТУАЛЬНОГО НАЙЧАСНОГО Кейсу з показаним кодом 12 + 75 + 55 + 34 + 1 + 4 = 181 біт

FIQ показує два вдосконалення цієї простої схеми, але їх важче кодувати :

  • Видаліть біт 2 з кодування шматка в рядках 1 і 8, оскільки пішаки не можуть туди переходити (до 16-бітної економії)
  • Використовуйте пішаків для кодування граючих граків (4-бітна економія)

Єдиний залишився код, не відображений у цій відповіді (для стислості): розбиття вхідного FEN у полях ( split /\s/) та присвоєння змінної.


Гравець може просувати всі свої пішаки (враховуючи, що він здатний захоплювати пішаків противника); Qn4QQ / Qb6 / Qq1k4 / Qr6 / Qb6 / Qr6 / Qn4NK / RNB2B1R b - - 0 84
Krzysztof Szewczyk

@KrzysztofSzewczyk, так, що зазначено вище на PPpp=>QQq_
Вільям Ентрікен

4

Всього потрібно 33 байти

(Дякую комусь у коментарях, я зрозумів, що це не працює для просування пішаків. Оновіть це, коли зможу це вирішити)

для першого байту ми використовуємо п'ять біт:

  • перший біт: черга гравця, 1 = білий
  • другий біт: замок чорного короля, 1 = замок
  • третій біт: чорний замок бічної королеви, 1 = замок
  • Четвертий біт: Білий король замок, 1 = замок
  • п'ятий біт: біла королева бічний замок, 1 = замок

наступні 32 байти використовуються для представлення кожної шахової фігури у визначеному порядку

  • 3-біт: представляють рядок
  • 3-біт: представляють стовпчик
  • 1-біт: представляють en-passant, 1 = can en-passant
  • 1-біт: якщо біт "can en-passant" дорівнює 1: вказує, яка сторона, 0 = лівий
    інший представляє, чи був він захоплений. 0 = не захоплено
    (Якщо він може бути перехідним, то він точно не захоплений)

Якийсь код C, який представляє цю ідею (який насправді не працює)

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, це не відповідь ...
Дверна ручка

1
Ваш зумовлений порядок не буде багато користі , коли пішак досягає восьмий ранг і призначена на лицар, єпископ, човен або ферзь.
пискливе костіння

@Doorknob of Snow нормально Я працюю над алгоритмом, це трохи пізно вночі, і я втомився, тому я роблю це трохи повільніше
pastebin.com slash 0mr8spkT

Ну чому тоді ви це опублікували, якщо у вас навіть немає рішення?
Дверна ручка

3
якщо ви все ще вважаєте, що ця відповідь - це лайно і не має значення тут, тоді продовжуйте і голосуйте, щоб видалити її та зняти з неї, і ви можете також видалити мій рахунок тут. я просто хочу поділитися тим, про що я міг подумати, чому ви, хлопці, повинні бути такими злісними?
pastebin.com slash 0mr8spkT

4

256 242 біт

Ось основний алгоритм стиснення, який, ймовірно, можна вдосконалити, оскільки він не виключає представлення певних незаконних позицій.

Дошка починається з 5 бітів інформації заголовка таким чином:

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

Потім, рядок з 12 біт, що представляють позиції королів.

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

Потім, величезне 64-розрядне число в базі 11, яке потім множать на 9, щоб додати ще одну цифру в кінці, що представляє стан енсасанта. Кожна цифра в базі 11 являє собою квадрат на дошці з наступними можливими значеннями:

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.

І цифри в базі 9:

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

11 64 × 9 - це приблизно 2 224,57 , що для кодування вимагає 225 біт. Плюс 17 біт заголовка вгорі - це 242 біти.


Завдяки угорену за покращення.


Це дуже схоже на алгоритм туза, але він використовує позиції плати замість штук у заздалегідь визначеному порядку, що обидва виключає її з проблемою просування пішаків і дозволяє трохи відсікати дані.
Джо З.

Ви можете зберегти en-passant як одне число від 0 до 8 (на якому стовпчику поточний програвач може записати en-passant?). 13^64 * 9становить 239,99, заощаджуючи 11 біт. Збережіть більше, кодуючи позиції короля окремо.
угорен

За словами Doorknob of Snow, який коментував мій пост, така відповідь - це "не відповідь". Просто кажу. FYI його коментар був опублікований ще до того, як я додав код С у свою відповідь.
pastebin.com slash 0mr8spkT

@ugoren: Я забув про це. Ви маєте рацію, я забув, що лише одна пішака може бути одночасно прохідною.
Джо З.

@ace: Ваша відповідь недійсна, оскільки вона не включає код кодування та декодування; він недійсний, оскільки він не враховує випадок просування пішаків (у цьому випадку ваш попередньо визначений порядок творів нічого не робить). Проблема, по суті, запитує схему кодування даних. Програма - це щось, що поєднує з цим.
Джо З.

3

? біт

(≥ 217 в гіршому випадку, 17 найкращих, 179 для початкової ради)


Опис кодування

Додаткові метадані складаються з повороту якого (один біт) та відливання (чотири біти, тобто може білий замок на стороні королів? На стороні королеви? Та аналогічно для чорної).

Для самого положення дошки ми кодуємо це як набір активних фрагментів. Ну, власне, ми обов'язково перераховуємо шматки в певному порядку з причин, які я поясню трохи. Для кожного твору ми зберігаємо його колір (один біт), його вид (три шматочки, що охоплюють 6 видів, плюс один додатковий вид для «пішака, який може бути зайнятий на пасажі»), а також його положення.

Ось цікава частина: щоб кодувати положення шматка, замість того, щоб зберігати його як координату, ми зберігаємо його відносну відстань від останнього шматка при перерахуванні шматочків у порядку зліва направо зверху вниз (тобто A8 , B8, ..., G1, H1). Крім того, ми зберігаємо відстань як число змінної довжини, маючи 1на увазі, що ця деталь знаходиться прямо поруч із попередньою, 0xxдля пропускання 1-3 штук, 000xxxдля пропускання 4-10 штук, 000000xxxxдля 11-25, 0000000000xxxxxдля 26-56 і нарешті 000000000000000xxxза 57-62.

Приклади

Я зробив суть деяких позицій, зашифрованих цим кодуванням, і заздалегідь відзначив позицію для початкової позиції.

Я не знаю, як проаналізувати найгірший розмір бітів, але, йдучи за прикладами в суті, я вважаю, що алгоритм повинен бути принаймні ефективним.


Реалізація декодера

Нижче наводиться швидкий і брудний декодер для цього кодування (взяття як вхід бінарних даних, закодованих у тексті, як у наведеному вище примітці, та пропускання над речами, які не є "0" або "1"). Виготовляє шахову дошку з унікодом для виведення.

#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;
}

Я поняття не маю, який ваш найгірший біт, але я підозрюю, що це значно більше 179 біт. Наприклад, як би ваш алгоритм поводився з цим макетом ? (Це є дійсним, до речі, я зробив це з допомогою редактора на chess.com )
гидливо грифа

@squeamishossifrage, що, здається, вимагає 217 біт: gist.github.com/FireyFly/8639791 (спасибі за тестовий випадок, я хотів спробувати це з хитрішим!)
FireFly

Гей, це непогано. Продовжуй!
пискливе костіння

2

Макс: 184 біта, Мін: 75 біт

Мене надихнуло кодування Хаффманом @ AdamSpeight для того, щоб спробувати створити власну схему. Я сумніваюсь, що це виграє, але у нього є обмежувані кількості.

Ця схема розглядає шахові фігури так, ніби існує 11 різних типів фігур. Я приблизно дотримувався алгоритму кодування Хаффмана, щоб групувати ці класи за їх частотами та реальними типами, щоб генерувати такі кодування:

 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

Коду кожної частини може передувати два біти, щоб показати, до якої команди вона належить ( 10для White, 11for Black). 0може використовуватися для кодування порожніх пробілів. Ці ідеї дозволяють нам побудувати кодування квадратного квадрата для всієї дошки, використовуючи будь-яку процедуру, яку ми хочемо. Я візьму на себе ітераційний порядок a1, b1, c1, ... f8, g8, h8. Це означає, що лише перелік цих кодів, як показано вище, кодує всю інформацію, за винятком того, чия черга. Дуже простий шаховий двигун може використовувати "класи" для пішаків, граків та королів, щоб визначити, чи є законними переходи та пасанти. Крім того, ця схема легко обробляє рекламу пішаків. Якщо гравець просуває пішака до грака, можуть бути використані або король, або королева на стороні коду до тих пір, поки буде обраний варіант "переміщений".

За винятком патологічних позицій, які, на мою думку, ніколи не могли відбутися, найгірший сценарій цього кодування - це коли всі фігури все ще на дошці, а попередній гравець перемістив пішака вперед на два місця. Як приклад, дошка нижче кодує 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

Це означає, що найгірше кодування має 184 біти: 1 для вказівки гравця, 32 для порожніх просторів, 45 для пішоходів, що не пересуваються, 6 для пішаків, що стрибають з двох просторів, 24 для лицарів, 24 для єпископів, 28 для граків, 12 для цариць і 12 для царів.

Коли шматки переміщаються і захоплюються, розмір кодування зменшиться. Найкращий сценарій представлений двома королями на дошці: 1 біт для позначення гравця + 62 біта для індикації порожніх квадратів + ​​12 біт для вказівки королів дає мінімальну довжину 75 біт.

Я повернусь і відредагую цю відповідь деяким кодом, який демонструє це кодування в дії пізніше сьогодні чи завтра. Наразі мені цікаво побачити, що інші люди думають про це кодування.


1
Можна зберегти біти на граках. Ви можете визначити королеву та короля на основі позиції, і вам не потрібно знати, з якої сторони прийшов переїзд. тому вам потрібен лише один біт інформації про ладья - переміщений чи не переміщений.
Не те, що Чарльз

... І насправді, зберігати ці дані на рівні частини простіше кодувати / декодувати, але якщо ви просто зберегли маркер на старті, ви можете зберегти біти в загальному випадку (наприклад, маркер 11001означає B'S MOVE W CAN KSC W CANT QSC B CANT KSC B CAN QSC). Це 4 біти замість 5 біт на кожну сторону кодування, або 3 біти на сторону, якщо ви усунете бічний маркер на граках. ( KSC= Замок з боку короля. QSC= Замок з боку королеви)
Не те, щоб Чарльз

Також, завдяки рекламним акціям, цілком можливо мати до 9 королеви чи 10 лицарів (або будь-яку іншу нерегулярну, не пішачу фігуру)
Не те, щоб Чарльз

1

184 біт = 23 байти, найгірший випадок, і не надто складний:

A. Які квадрати займали: 64 біти = 8 байт B. Які кольори для <= 32 зайнятих квадрата: 32 біта = 4 байти. А тепер використовуйте лише <= 30 квадратів, зайнятих не царями: B. використовуйте PNBRQ, закодовані в радіусі 5, для 5 ^ 30 можливостей; і 32 * 31 * 2 * 4 * 4 * 9 для королівських позицій, кольори рушій, біло-чорні права на замку, на прохідній площі (серед 8 можливостей плюс жодна, 9-а); це число 5 ^ 30 * 32 * 31 * 2 * 4 * 4 * 9 = 266075134277343750000000000 = 2 ^ 87.782 вміщається в 88 біт на загальну суму 64 + 32 + 88 = 184 біта для всього кодування.

Це можна зменшити, наприклад, 32 * 31 * 2 * 4 * 4 * 9 = 285696 можна зменшити до 2 * (32 * 31 + 31 * 3 + 31 * 3 + 3 * 3) * 6 = 14244, використовуючи факт щонайменше 6 en пасивних кандидатів-жертв (включаючи жодних), і кодування прав на замку та королівських позицій всередині одного набору, використовуючи права на каталітичний факт, має значення лише тоді, коли король на початковій площі. Це економить 4 біти.

У мене є підстави вважати, що досягти 18 байт неможливо, тобто загальна кількість законних шахових позицій перевищує 2 ^ 144.

Ваша 160-бітна схема дуже геніальна, але я думаю, що її потрібно надати як програми кодування / декодування, перш ніж я буду повністю впевнений у цьому.


1

171 біт найгірший випадок:

Я поєднав пару ідей, а також кілька власних думок.

Ми почнемо з 64-бітної плати. Кожен біт являє собою зайняте місце на дошці. Вони заповнюються по рядах. Тож початок виглядає так:1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111

Тепер кожен шматок буде представлений 4-ю бітами. 1-й біт: color ( 0=white, 1=black) 2-й-4-й біт: Один з 8 типів.

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

Наприкінці ми включимо трохи позначення повороту. 0=white, 1=black.

4 біт * 32 штуки = 128 біт, і я вже отримав 64 + 1 з повороту та дошки. Це дає в цілому 128 + 64 + 1 = 193, я навіть не почав займатися пасажами чи роками. Ну за мою межу ні з чим - навіть не обертається. Тут починаються трюки.

Гаразд - ви бачите ці типи вище? Bishop0 та Bishop1? Пішак0 і пішак1? Ці типи так позначені, тому що вони говорять нам трохи вставити після цього твору. Отже Bishop0 означає, що після нього буде 0 - тобто наступний шматок - білий. Bishop1 каже нам, що наступний твір - чорний, а пішак0 та пішак1 працюють однаково. (Якщо ця п’єса є останньою частиною, яка перераховується, то вона говорить нам про наступну чергу, замість цього).

Мій найгірший випадок включає всі шматки на дошці, тож з 16 пішаками та 4 єпископами це зекономить мені 20 біт. Я знижуюся до 173.

Гаразд. Ще один біт у моєму гіршому випадку - як тільки 16 закодованих кольорів, ми припиняємо кодування кольору - оскільки ми знаємо, що він рухається вперед. У моєму найгіршому випадку зараз є білий шматок, який робить його в далекому куті без захоплення. Там я економлю лише один шматочок. 172.

Зараз я буду змінювати порядок, в якому я називаю твори. Ми будемо називати їх уздовж стовпців, починаючи з зовнішньої переміщення. Дошка, названа на початку, залишиться такою ж, але коли я розміщую на ній шматки, я починаю з білих праворуч знизу, і йду вгору до цього стовпця. Тоді я стрибаю до чорного знизу праворуч і йду вгору по цій колонці. Я стрибаю до білої нижньої правої невідомої клітини і так далі - це означає, що мій гірший випадок - це знову початок. Моя причина пов’язана з моїм пасивним трюком, наступними двома бітами, які я втрачаю, та з роллю.

Тепер, щоб пішак пішов (як уже було обговорено), шматок повинен бути захоплений. Таким чином, коли ми знаємо, що їх є 32, нам потрібно лише позначити 31 з них. Останній твір однозначно ідентифікований. Як виявляється, для мене це заощаджує лише 2 біти - тому що мій останній шматок може бути пішаком / єпископом (який зазвичай коштує мені 3 біти, тому що я зберігаю один на наступному творі), який колір вже визначений, і таким був лише 2 біти. Я знижуюся до 170 біт.

Коли пішаки отримують підвищення, вони просто змінюють свій тип. За кожну частину, яка виходить з дошки, я позбавляю себе (мінімум) 3 біт, а дві рекламні пішаки коштують мені 2 біти, тому я знижую (повільно) рекламні акції.

Кастинг. Щоб це не відбулося, ні король, ні відповідний грак не могли рухатися. Таким чином, коли грак здатний закинути і його, і король опиниться на своїх початкових місцях. Отже, граки, здатні до закидання, будуть перераховані там же, що і королі цього кольору. Оскільки це незаконне (на дошці два королі або три королі одного кольору) і може траплятися лише у трьох можливих налаштуваннях для кожного кольору (лівий, правий, обидва граки вказані як королі) - розшифровка є цілком можливою. Отже, без жодних шматочків ми закодували замку.

En Passant Тут ми також використовуватимемо незаконні посади. Лише одна пішачка може загрожувати загрозою проникнення пасажирів. Він повинен бути в четвертому ряду. Вразлива пішак буде "перекинута" назад до свого домашнього ряду - переключиться на все, що там є. Оскільки пішак у своєму першому ряду - незаконне положення, ситуація буде очевидною для декодера - вона переверне положення і позначить пішака як вразливого для пасажира.

Нам потрібно було розібратися з замовленням, оскільки останній твір має бути "однозначно ідентифікований". У стандартному порядку ми б не змогли сказати, чи може грак у задньому куті замок - це невідомо. Коли ми працюємо ззовні, ми гарантуємо, що там, де цей грак буде «перерахований», будь то в його власному куті, або посередині дошки, оскільки він був переключений із вразливою пішаком пішака, буде фрагмент, перерахований після це - так нам кажуть тип грака. Ми знаємо, що після цього буде шматок, тому що для вразливості пішака повинна бути пішака до її внутрішньої сторони (яка буде вирішально закодована пізніше згідно з інструкціями вище).

О, і щоб переконатися, що найгірший випадок включає всі шматки на дошці, як тільки у нас буде менше 32 штук, ми можемо використовувати 64-бітну дошку для ідентифікації повороту, а також зайнятих позицій, використовуючи 0, щоб представити шматки, коли її білі поворот і 1-х, коли це чорні черги.

Таким чином, ми отримали ан-пасант та кастинг безкоштовно. Ми зібрали останній твір безкоштовно, хоча це зайняло певний фіналінг для того, щоб зробити цю гру хорошою з правилами en passant та castling. Ми викреслили 20 стандартних шматочків. Я вважаю, що найгірший випадок, що стосується білої пішаки, що рухається вперед, і чорного шматка між нею та її королевою, поки всі шматки знаходяться на дошці. Швидка подвійна перевірка: перший шматок захоплений - називаємо його пішаком, 3 біти від дошки на пішаку, 3 біти на дошці у вигляді останнього шматка, один шматочок у маркері повороту зникає. Просувайте дві пішаки 2 біти назад на дошці. Ах, чорт, я в 171.

EDIT Я додав код для (робочого?) Декодера - в R - нижче. Він приймає вектори булевих сигналів як вхідні дані (вибачте - я не здатний добре кодувати все, що дозволило б мені реально використовувати біти) Я також включив початкову позицію.

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

Цей код будує 4 функції. Той, який робить деяке основне розділення частин та структури дошки, а також з'ясування типу шматка та будь-яких "неявних" фрагментів. Наступна функція заповнює структуру дошки з тими фрагментами у дещо химерному (і відмінному від мого початкового алгоритму) порядку [пояснено в коментарях до коду]. Наступна функція приймає заповнену дошку та виявляє будь-які незаконні позиції - потім вона виправляє їх та перейменовує пішаки, вразливі до прохідних "x pawn-e" та будь-яких граків, які можуть замку "x rook-c". Заключна функція - обгортка, яка виконує ці функції в порядку і дає вихід, який є поточною дошкою, а також поворот.

Я також включив кодування початкової позиції (хоча, щоб побачити це, вам доведеться зателефонувати, c(startboard,newpieces)і код викликає функцію обгортки на цій позиції.


Це цікаво. Я хотів би бачити робочу реалізацію як доказ концепції.
Mego

Реалізація зазвичай на кілька кроків, що перевищує доказ концепції, але я додав декодер. Це в R і, таким чином, використовує булеві, а не біти (вибачте - не хотів використовувати занадто багато часу). Але я вважаю, що це має бути доказом концепції.
користувач5957401

0

229/226 біт

Це виявляється не дуже успішним, але може врятувати інших людей, що йдуть тим самим шляхом.

Проста версія:

  • 1 біт, чия черга
  • 4 біт для чотирьох можливостей лиття
  • 3біт для прохідних можливостей. Це має більшу глибину, яку я спочатку зрозумів. Проходження пасанта повинно бути зроблено пішаком, що рухається з того ж рангу (ряду), що і пішак, який захоплений. Аналіз випадку свідчить про те, що як тільки ми дізнаємося, скільки пішаків пішло в останній колір, просунулося рівно два квадрати, то буде щонайменше 6 випадкових випадків (включаючи випадок, коли пішака не є вразливою для пасажира ). Гірший випадок - це 5 пішаків (потенційно всі вразливі: наприклад, PpPPpPPpмає п'ять уразливих груп P). З 6 пішаками є щонайменше 2 пішаки ворога в тому ж ранзі, кожна з яких може загрожувати не більше ніж 2 пішакам . Тому нам потрібні ceil(lg 6) = 3шматочки.

Потім дошка. Дошка має 64 квадрата, тому квадратний індекс можна закодувати в 6 біт. Ми перераховуємо чоловіків за рангом, чергуючи кольори, починаючи з короля.

  • 6біти: положення білого короля. (Гарантоване бути на дошці).
  • 6біти: положення чорного короля. (Гарантовано, що він знаходиться на дошці. У гіршому випадку, коли білий король знаходиться у кутку, він може бути 60 можливих місць; в кращому випадку, якщо біле не на краю, є 55).
  • 6біти: положення білої королеви. Якщо немає білої королеви, повторіть позицію білого короля як сигнал.
  • Для кожної додаткової білої королеви 1трохи слід за 6 бітами для позиції.
  • 0Біт.
  • Дітто для чорної королеви.
  • Аналогічний процес для граків, єпископів, лицарів та пішаків, хоча ми можемо пропустити пішаків за кольором, якщо у нас уже 16 чоловік такого кольору.
  • Видаліть заключний 0біт.

Це коштує певних 12бітів для королів, а 2*7*5-1 = 69бітів для інших людей. У гіршому випадку, якщо всі 32 чоловіки перебувають на борту, це коштує 7бітів для кожного чоловіка, крім царів, в цілому 12 + 7*30 - 1 = 221 bits. Отже, з початкових 8бітів для глобального стану ми маємо 229 біт .


Розширена версія:

Використовуючи арифметичне кодування, ми можемо оперувати, lg num_possibilitiesа не ceil(lg num_possibilities)просто брати його ceilв кінці.

  • 1 біт, чия черга
  • 4 біт для чотирьох можливостей лиття
  • lg 6біт для прохідних можливостей.
  • 6 біти для білого короля
  • lg 60 біти (найгірший випадок) для чорного короля
  • lg 63 біт (тому що я не хочу ускладнювати це рівнем перегляду чеків) для білої королеви, використовуючи положення білого короля, якщо такого немає
  • Для кожної додаткової білої королеви, 1трохи за нею lg 62, lg 61і т. Д. Біти для її положення.
  • 0Біт.
  • lg 63 біт (або менше, якщо були білі королеви) для чорної королеви.
  • тощо.

П'ятий чоловік, який насправді присутній, має 66-nможливі цінності. Якщо тип відсутній для кольору, ми витратили 66-#men so farбіти на запис (плюс один біт для роздільника). Крайні випадки:

  1. Всі присутні чоловіки, включаючи принаймні по одному піхотному пішаку з кожного боку. Ми витрачаємо 5+lg 6на глобальну державу, 6+lg 60на королів, 29на сепараторні біти та SUM_{n=32}^{63} lg nбіти на позиції. Великий загальний: ceil(225.82)біт. Розчарування.
  2. Залишилися лише нерекламовані пішаки. Ми витрачаємо 5+lg 6на глобальну державу, 6+lg 60на королів, 29на сепараторні шматочки, 8*lg 63кажучи, що інших частин немає і SUM_{n=48}^{63} lg nна позиції пішаків. Великий загальний: ceil(188.94)біт. Краще - врятувавши другий грак, лицар та єпископ для кожної сторони, ми трохи потягнули вперед.

Тож найгіршим випадком може бути 226 біт , за неміцну економію 3.

Ми, безумовно, можемо зробити краще в середньому випадку, кодуючи пішаків перед шматками, оскільки вони обмежені до 48 квадратів, а не до повних 64. Однак, у гіршому випадку, якщо всі чоловіки на дошці, і всі пішаки були підвищені, я думаю це в кінцевому рахунку обійдеться на 2 біти дорожче, тому що нам знадобиться прапор без пішаків, а не можливість рахувати чоловіків.


0

Це тема дискусії у шахових колах.

Ось один дуже простий доказ із 164 бітами https://groups.google.com/forum/#!topic/rec.games.chess.computer/vmvI0ePH2kI 155 показаний тут http://homepages.cwi.nl/~tromp /chess/chess.html

Над спрощеною стратегією:

  • Обмежте пішаків до місця, де можна знайти пішаків
  • Обмежте армію, щоб врахувати оригінальні фігури та можливі акції пішаків
  • Подумайте над акціями та ситуаціями, коли промоція неможлива

2
Відповіді лише на посилання - це не гарні відповіді. Ви повинні дати повну відповідь у своєму дописі, а не лише деякі посилання на відповідь. І якщо ваша відповідь - це не ваша власна робота, ви, ймовірно, повинні зробити свою публікацію вікі спільноти.
pastebin.com slash 0mr8spkT

Повідомлення оригінальне. Додавання деталей для відповіді.
Вільям Ентрікен

1
Це приклад того, чому ви включаєте вміст у свою відповідь. 2-а ланка мертва. Це це? tromp.github.io/chess/chess.html
mbomb007

-2

Мінімум: 0 біт

Макс: 1734 рік 243 біта (4.335 4.401 біт / амортизована плата)

Очікується: 351 177 біт (4.376 4.430 біт / амортизована плата)

Оскільки я можу визначити вхід і вихід, проте я хочу, щоб я вирішив перейти до кодування історії гри до цього моменту. Однією з переваг є те, що додаткова інформація про те, хто її черга, всебічний та хто має можливість замовити там, де його можна отримати, а не закодувати.

Спроба 1:

Наївно я подумав, що можу кодувати кожен хід у 12 біт, 4 трійки форми (початок х, початок у, кінець х, кінець у), де кожен - 3 біти.

Ми би прийняли вихідне положення і перемістимо шматки звідти, коли білим буде перший. Дошка розташована таким чином, що (0, 0) є нижній лівий кут білого кольору.

Наприклад гра:

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

Буде кодовано як:

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

Це призводить до кодування 12 м біт, де m - кількість зроблених ходів

З одного боку, це може стати справді великим, а з іншого - ви можете вважати, що кожен крок - це власна гра, тому кожне кодування дійсно кодує m «шахові дошки». Якщо ви амортизуєте це, ви отримуєте, що кожна «шахова дошка» - 12 біт. Але я відчуваю, що це трохи обман ...

Спроба 2:

Я зрозумів, що кожен крок у попередній спробі кодує багато незаконних кроків. Тому я вирішив кодувати лише юридичні кроки. Перерахуємо можливі рухи наступним чином, пронумеруємо кожен квадрат таким, що (0, 0) → 0, (1, 0) → 1, (x, y) → x + 8 y. Перебирайте плитки і перевірте, чи є там шматок і чи може він рухатися. Якщо так, додайте позиції, до яких можна перейти до списку. Виберіть індекс списку, який ви хочете зробити. Додайте це число до загальної кількості ходів, зважених на 1 плюс кількість можливих ходів.

Приклад, як описано вище: З початкового положення перший фрагмент, який може переміститися, - лицар на квадраті 1, він може перейти до квадрата 16 або 18, тому додайте їх до списку [(1,16),(1,18)]. Далі - лицар на площі 6, додайте, що це ходи. Загалом ми отримуємо:

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

Оскільки ми хочемо рухатись (12, 28), ми кодуємо це як 13 в базі 20, оскільки існує 20 можливих переходів.

Отже тепер отримаємо ігрове число g 0 = 13

Далі робимо те ж саме для чорного, за винятком нумерації плиток у зворотному порядку (щоб було простіше, не потрібно), щоб отримати список ходів:

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

Оскільки ми хочемо рухатись (11, 27), ми кодуємо це як 11 в базі 20, оскільки існує 20 можливих переходів.

Отже тепер отримаємо ігрове число g 1 = (11 ⋅ 20) + 13 = 233

Далі ми отримуємо такий список ходів для білого:

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

Оскільки ми хочемо рухатись (6, 21), ми кодуємо це як 13 в базі 29, оскільки існує 29 можливих переходів.

Отже тепер отримаємо ігрове число g 2 = ((13 ⋅ 20) + 11) 20 + 13 = 5433

Далі ми отримуємо наступний список ходів для чорного: [(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)]

Оскільки ми хочемо рухатись $ (10, 18) $ (10, 18)

Отже тепер отримаємо ігрове число g 3 = (((19 ⋅ 29 + 13) 20) + 11) 20 + 13 = 225833

І продовжуйте цей процес для всіх решти кроків. Ви можете вважати g функцією g (x, y, z) = x y + z. Таким чином, 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)

Для розкодування ігрового числа g 0 , ми починаємо з початкової позиції і перераховуємо всі можливі рухи. Тоді обчислюємо g 1 = g 0 // l , m 0 = g 0 % l , де l - кількість можливих переміщень, '//' - оператор цілочисельного поділу і '%' - оператор модуля. Має бути встановлено, що g 0 = g 1 + m 0 . Далі робимо хід m 0 і повторюємо.

З наведеного вище прикладу, якщо g 0 = 225833, то g 1 = 225833 // 20 = 11291 і m 0 = 225833% 20 = 13. Далі g 2 = 11291 // 20 = 564 і m 1 = 11291% 20 = 11. Тоді g 3 = 11291 // 20 = 564 і m 2 = 11291% 20 = 11. Тому g 4 = 564 // 29 = 19 і_m_ 3 = 564% 29 = 13. Нарешті g 5 = 19 // 29 = 0 і m 4 = 19% 29 = 19.

Так скільки бітів використовується для кодування гри таким чином?

Для простоти, скажімо, завжди є 20 рухів на кожному повороті, а для найгіршого сценарію ми завжди вибираємо найбільший, 19. Число, яке ми отримаємо, становить 19 ⋅ 20 м

+ 19 ⋅ 20 m-1 + 19 ⋅ 20 m-2 + ⋯ + 19 ⋅ 20 + 19 = 20 m + 1 - 1, де _m - кількість ходів. Для кодування 20 m + 1 - 1 нам потрібно приблизно log 2 (20 m + 1 ) біт, що приблизно (m + 1) ∗ log 2 (20) = 4.3219 ∗ (m + 1)

В середньому m = 80 (40 ходів на гравця), так що для кодування потрібно 351 біт. Якщо ми записували багато ігор, нам знадобилося б універсальне кодування, оскільки ми не знаємо, скільки бітів знадобиться кожному номеру

Найгірший випадок, коли m = 400 (200 ходів на гравця), так що для кодування знадобиться 1734 біт.

Зауважимо, що позицію, яку ми хочемо кодувати, потрібно дати нам найкоротшим шляхом, щоб дістатися туди, дотримуючись правил. Наприклад, для теоретизованої гри тут не потрібно m = 11741 для кодування кінцевої позиції. Замість цього ми проводимо пошук "Перша ширина", щоб знайти найкоротший шлях до цієї позиції і замість цього кодувати. Я не знаю, наскільки глибоко нам потрібно було б перерахувати всі шахові позиції, але я підозрюю, що 400 є завищеною.

Швидкий розрахунок:

Є 12 унікальних фігур або квадрат може бути порожнім, так що розташувати їх на шаховій дошці - це 13 64 . Це велика завищення, оскільки воно включає багато недійсних позицій. Коли ми м рухається в грі ми створили близько 20 м позицій. Тож ми шукаємо, коли 20 м = 13 64 . Запишіть обидві сторони, щоб отримати m = 64 * log 20 (13) = 54.797. Це показує, що ми повинні мати можливість дістатись до будь-якої позиції за 55 рухів.

Тепер, коли я обчислив найгірший випадок, коли m = 55 не m = 400, я відредагую свої результати. Для кодування позиції, де m = 55 займає 243 біта. Я також скажу, що середній випадок становить близько m = 40, що кодує 177 біт.

Якщо ми використовуємо аргумент амортизації раніше, ми кодуємо 400 «шахових дощок» у 1734 бітах, тож ми отримуємо, що кожна «шахова дошка» займає 4,335 біт у гіршому випадку.

Зауважте, що g = 0 позначає дійсну гру, ту, де шматок на нижньому квадраті переміщується до найнижчого квадрата, який він може.

Додаткові нотатки:

Якщо ви хочете вказати певну позицію в грі, можливо, вам знадобиться кодувати індекс. Це можна додати або вручну, наприклад, об'єднати індекс у гру, або додати додатковий хід "кінця" як останній можливий хід кожного кроку. Тепер це може призвести до того, що гравці поступилися, або 2 поспіль, щоб позначити гравців, які погодилися на нічию. Це необхідно лише в тому випадку, якщо гра не закінчилася маткою чи тупиком на основі позиції, в цьому випадку це мається на увазі. У цьому випадку кількість бітів, необхідних в середньому, становить 356, а в гіршому - 1762.


1
Ваш аргумент "амортизація" не працює. Мета - кодувати дошку, задану користувачем. Ви не ділите витрати на кодування цієї плати між 400 допоміжними дошками, які, можливо, ви будете генерувати на цьому шляху. (Це було б добре, якби ці 400 дощок дозволили самостійно обирати користувач, а не обмежуватись вимогою формувати шахову гру.) Також шахова гра теоретично може робити багато тисяч рухів , і ОП є чітко про те, що цікавиться найгіршим випадком.
Anders Kaseorg

@AndersKaseorg: Дуже правда. Це дійсно залежить від мети. Якщо ви намагаєтесь зберігати цілу гру з усіма іншими алгоритмами, знадобиться m * c байт, де m - кількість ходів, а c - розмір їх виходу. Тож якщо ви намагаєтесь зберегти цілу 80 рухову гру за допомогою 160-бітного рішення, це зайняло б 12800 біт, а моє - 351. Заради конкуренції я визнаю, що ви вірні, але я подумав, що це була хороша властивість зазначити, оскільки дуже часто хочеться зберігати цілі ігри, а не лише дошки.
edggy

Мета однозначна. «Мета полягає в тому, щоб зробити найменше представлення шахової дошки, яку можна було б використати (колись розшифрувати), щоб визначити всі можливості руху гравця на цьому кроці. … Ваш результат визначається в гіршому випадку - максимально можливий розмір у бітах. ”
Anders Kaseorg

@AndersKaseorg: Я ніколи не стверджував, що це неоднозначно. Я просто вирішив застосувати інший підхід. Варто зазначити одне, щоб знайти найменшу дошку за допомогою мого алгоритму. Мені потрібен найменший шлях, щоб дістатися до цієї позиції. Наприклад, у грі 11741 повороту, яку ви пов’язали, щоб дістатися до тієї самої позиції на дошці, мені не потрібно слідувати цим шляхом, якщо нам все це важливо. Отже, для кодування зв'язаної гри я просто знаходжу найкоротшу гру, на якій залишаються 2 королі на тих квадратах, які можуть бути лише 200 оборотів або менше. Це можна зробити за допомогою першого глибинного пошуку.
edggy

Використання коротшої еквівалентної гри чудово, якщо ви дійсно можете довести, що кожна позиція доступна в 200 обертів або менше (зараз це виглядає як лише здогадка). Вам також потрібно буде враховувати шахові позиції з більш ніж 100 легальних кроків , якщо ви не зможете довести, що вони не виникають у вашій конструкції. Ділення результату на кількість рухів у грі досі заборонено правилами цього виклику.
Андерс Касеорг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.