Наименьшее сжатие шахматной доски


39

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

Кодировка должна быть в состоянии показать:

  • Чья это очередь?
  • Может ли игрок замок на каждой стороне.
  • Может ли игрок выполнить эн-пасса, и если да, то какая из его пешек?
  • Позиции всех фигур.

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

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

Определите вход и выход при необходимости. Основные реквизиты для тех, кто может сжать его больше всего!

Ваша оценка определяется наихудшим сценарием - максимально возможным размером в битах. Убедитесь, что вы показываете, как вы рассчитали это число и что вы учли. Стреляй в самый маленький наихудший случай!


Что вы подразумеваете под «побитовой»?
Питер Тейлор

Это самый маленький код или самый сжатый? Наиболее сжатым является более интересным.
Джастин

Извините, что не разъяснил. Побитовый в том смысле, что вы можете сжать его, только если начнете представлять его как биты, что потребует некоторой побитовой операции. Плохое использование с моей стороны. Также самый сжатый, а не маленький код.
Зельцер


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 бит !

Так что насчет К +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

Так что на короле +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 бит


ред 3

Мин .: 82 Макс .: 199 Средний: 160

Наконец-то удалось немного проанализировать, чтобы найти максимальный размер бита. С оптимальным кодированием Хаффмана для каждой из уникальных частот .

               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 бит для en passant. Не более одной пешки переместилось в последний ход, поэтому достаточно четырех битов (например, 1111для «невозможного прохода» или для столбца в виде двоичного числа в противном случае).
Питер Тейлор

Почему пешки занимают лучшую позицию на дереве? В общем случае они наиболее распространены, но в крайних случаях R / B / N могут появляться 10 раз.
Угорен

@PeterTaylor, на самом деле 3 бита достаточно для en passant. Если вы учитываете только столбцы с черной пешкой 5-го ранга (при условии, что ход белых), 8 становится недействительным.
Угорен

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

2
Обратите внимание, что для кодирования 64 позиций (для белого или черного короля) вам нужно 6 бит (2 ** 6 = 64).
ЛамбрускоАсидо,

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

    Чтобы закодировать дополнительную информацию, необходимую для правил en passant и castling, мы вводим один дополнительный тип фигуры, который обозначает пешку или ладью в зависимости от строки, на которой он появляется:

    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! Я реализовал ваше предложение. (Предложение Питера Тейлора, конечно, еще более эффективно, но я не использовал его до сих пор, потому что мне нравится простая двоичная кодировка текущей схемы. Вы всегда можете представить ее как отдельную запись ...)
Ilmari Каронен

Хорошо, это немного сложно. Но выслушай меня. Если вы просто возьмете 1-битный удар по индикатору поворота, вы можете заменить короля ходом на фигуру, которую я называю pawn1. Измени пешку на пешку0. Теперь, когда есть пешка (не пассивная уязвимая) - вы также получаете один бит информации о следующей фигуре (0 для пешки 0 или 1 для пешки 1). Поскольку есть 16 пешек, вы получаете на 16 бит меньше 1 для индикатора поворота. Всякий раз, когда есть пешка, которая уязвима для en passant, вы должны добавить один бит обратно после нее. Но так как en passant должен произойти немедленно, ваш минимальный выигрыш составляет 14 бит.
user5957401

Вы также можете сделать то же самое с чем-то вроде епископов. Предположим, что у вас есть слон, который не находится в «особой зоне» (10 точек в его углах и центральный ряд на его стороне) помечены как особые. Потому что вы знаете его местоположение - вы знаете, что это епископ. Теперь у вас есть два слона, и вы можете дать каждому из них 0 или 1 на следующем листе. Это дает еще 4 бита - но в наихудшем случае епископы во всех особых зонах не получают никакого выигрыша.
user5957401

14

160 бит в худшем случае

После публикации моего предыдущего ответа 22 байта я начал задаваться вопросом, можем ли мы сократить до 21 байта. Однако когда я увидел удивительные 166 байтов Питера Тейлора, я подумал: «Погоди, похоже, что пять 32-битных слов могут быть возможны!»

Поэтому, после долгих размышлений, я придумал следующее: 159,91936391 байт (довольно плотное прилегание!). Для этого уровня сжатия потребуется довольно сложная программа, но я подумал о том, как заставить ее работать в разумные сроки.

Это будет длинный пост, поэтому, пожалуйста, потерпите меня, я опубликую все, что смогу сегодня, и скоро добавлю несколько кусочков кода.

Итак, вот как это сделать:

En Passant и рокировка, закодированные недопустимыми позициями (0 битов)

Мимоходом

Как упоминалось в других ответах, существует максимум 5 возможных квадратов, на которых может стоять пешка, уязвимая для проходящего. Это квадраты рядом с пешками игрока, чей ход.

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

Чтобы это не мешало кодированию рокировки, важно, чтобы квадраты, на которых стоят короли в начале игры, не нарушались, и чтобы процедура кодирования en passant не помещала королей рядом друг с другом, что было бы незаконным положением короля. Чтобы удовлетворить вторую из этих точек, у кодера есть два выбора, на какую клетку он обменивает проходную пешку. Первый квадрат выбора для каждой из до 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

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

A. Рассмотрим одну акцию для черно-белых, предполагая, что человек, которого потеряли белые, может быть любого типа:

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

в конце вам удалось взять байты вместо битов, что вы и имели в виду, что может вызвать у читателей некоторую перепутку
masterX244

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,
Питер Тейлор

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

Выполнение этого на самом деле будет использовать 1 дополнительный бит. Причина в том, что (в худшем случае) может быть 5 возможностей для enpassant, но мне все еще нужно объявить возможность для «no enpassant», то есть 6-го состояния. 1 дополнительный бит в этом случае будет означать объявление enpassant возможным или нет (и с этим подходом я мог бы также использовать еще более простой подход с кодированием 30 частей, пропускающих блок enpassant, и использовать 3 бита отдельно для проверки enpassant, что также приведет к использованию +1 бита). В следующей 5-й строке будут включены 5 потенциальных участников (ход белых): BWBBWBBW
FIQ

Да, ты прав.
Алин Стоян

7

166 бит

  • 1 немного: чья это очередь?
  • 2биты: какие варианты рокировки открыты? (NB при внимательном прочтении вопроса, необходимо записать параметры рокировки только для игрока, чей это ход).
  • lg 6 ~= 2.585биты: какие варианты en passant открыты? (См. Мой другой ответ)
  • 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 захваченными мужчинами
Level River St

@steveverrill, то, что я действительно хотел бы сделать, это закодировать позиции пешки и количество продвижений в одном «блоке», а затем позиции и значения фигуры. Тем не менее, есть по крайней мере 2 38 позиций пешек без учета повышений, и их эффективное перечисление до сих пор ускользнуло от меня.
Питер Тейлор

@petertaylor Если у вас на доске только 16 пешек, ограниченных 48 клетками, у вас есть 48! / 32! / 8! / 8! = 29019905518636890 возможностей. Чуть больше 2 ^ 54! Некоторые из них являются незаконными, вы не можете иметь все пешки одного цвета на одной стороне доски.
Уровень River St

5

178 бит (174 в крайнем случае!) В худшем случае

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

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

А) Положение обоих королей: 6 бит каждый для белого и черного 12

Б) Из оставшихся 62 квадратов, которые заняты? Матрица 62 БИТОВ

В) чья это очередь?1 бит

ВСЕГО ТАК ДАЛЬШЕ: 75 БИТОВ

D) En Passant.Если очередь за ходом у белых, то до 5 черных пешек могут выглядеть так, будто они могут быть захвачены в Пассанте. Черная пешка должна быть в ряду 5 (снизу вверх, начиная с нуля), и рядом с ней должна быть белая пешка. Одна ситуация с максимальным количеством возможных захватов выглядит следующим образом:

BWBBWBBW

Если бы в ряду 5 было 6 черных пешек, у белых было бы только 2 квадрата, и они могли бы угрожать только 4 черным пешкам, поэтому невозможно одновременно иметь более 5 черных пешек, очевидно находящихся под угрозой со стороны Эн Пассанта. Таким образом, нам нужно число от 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 бит, как описано ниже.

Если ни одна фигура не была захвачена, то пешка не может быть повышена .

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

1) Черная пешка захвачена.

2) Черная пешка захватывает другую фигуру и, следовательно, уходит с дороги.

3) белая пешка захватывает пешку на соседнем столбце, таком как столбец D.

4) белая пешка проходит (или проходит мимо) черную пешку в соседнем столбце, а затем захватывает фигуру в том же соседнем столбце, заставляя белую пешку менять столбец.

Случай 4 является наиболее интересным, потому что не только белая пешка, которая началась в столбце E, теперь имеет четкий путь к продвижению. Черная пешка на столбце, который остается на столбце E, также может продвигаться. Поэтому один захват может расчистить путь для продвижения одной пешки каждого цвета.

В любом случае, тот факт, что никакая пешка не может продвигаться до тех пор, пока фигура не будет захвачена, означает, что нам не нужно хранить 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

A) Положение королей (восьмеричное / черное в белом, 12 бит ): 03 73 = 000011 111011

Б) Какие квадраты заняты? Начните с нулевого ряда (нижний ряд), затем всех остальных рядов сверху вниз, пропуская королей:

1111 111

1111 111
11111111
00000000
00000000
00001000
00000000
11110111 

C) ход черных: бит поворота = 1

D) 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 бита для хранения пассивных данных = 78 бит в лучшем случае. Каждая дополнительная часть имеет длину чуть менее 3,5 бит (2 части могут быть сохранены в 7 битах, потому что 100 <128.)

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

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


Хороший трюк с последним мужчиной.
Питер Тейлор

5

Вот полное решение, на самом деле худший случай 181 бит

Основное внимание здесь уделяется простой программе, которую вы можете легко понять

Ввод FEN, здесь позиция открытия, в ней шесть полей (5 и 6 игнорируются):

rnbqkbnr / pppppppp / 8/8/8/8 / PPPPPPPPP / 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 бита

Наихудший случай - продвигать все фигуры, а не оставлять пешку для en passant.

ВСЕГО АКТУАЛЬНОГО ХОРОШЕГО ДЕЛА С ПОКАЗАННЫМ КОДОМ 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
Кшиштоф Шевчик

@KrzysztofSzewczyk, да, это отмечено выше в PPpp=>QQq_
Уильям Энтрикен

4

Всего данных нужно 33 байта

(Спасибо кому-то в комментариях, я понял, что это не работает для продвижения пешки. Обновлю, когда смогу решить)

для первого байта мы используем пять битов:

  • первый бит: ход игрока, 1 = белый
  • второй бит: замок черного короля, 1 = может замок
  • третий бит: черный королевский замок, 1 = жестяная крепость
  • четвертый бит: замок белого короля, 1 = замок банки
  • пятый бит: белый королевский замок, 1 = жестяная крепость

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

  • 3 бита: представляют строку
  • 3 бита: представляют столбец
  • 1-битный: представляет en-passant, 1 = может 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 из Snow ok, я работаю над алгоритмом, немного поздно ночью, и я устал, поэтому делаю это немного медленнее
pastebin.com slash 0mr8spkT

Ну, тогда почему вы опубликовали это, если у вас даже нет решения?
Дверная ручка

3
если вы, люди, все еще думаете, что этот ответ является дерьмом и не имеет здесь никакого значения, тогда проголосуйте, чтобы удалить его и понизить его, и вы также можете удалить мой аккаунт здесь. я просто хочу поделиться тем, о чем я мог подумать, почему вы, ребята, должны быть такими подлыми?
pastebin.com косая черта 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, чтобы добавить еще одну цифру в конце, представляющую состояние en-passant. Каждая цифра в основании 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 * 9239,99, сохраняя 11 бит. Экономьте больше, кодируя позиции короля отдельно.
Угорен

По словам Doorknob of Snow, который прокомментировал мой пост, такой ответ "не является ответом". Просто говорю. К вашему сведению, его комментарий был опубликован до того, как я добавил код C в свой ответ.
pastebin.com slash 0mr8spkT

@ugoren: я забыл об этом. Вы правы, я забыл, что одновременно может быть только одна пешка.
Джо З.

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

3

? биты

(≥ 217 наихудших случаев, 17 лучших случаев, 179 для начальной платы)


Описание кодировки

Дополнительные метаданные состоят из чьего хода (один бит) и рокировки (четыре бита, т. Е. Могут ли белые замки на стороне королей, на стороне королев и аналогично для черных).

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

Вот интересная часть: чтобы закодировать положение фигуры, вместо того, чтобы сохранять ее как координату, мы сохраняем ее относительное расстояние от последней фигуры, когда перечисляем фигуры в порядке слева направо, сверху вниз (т.е. 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для белых, 11для черных). 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, закодированный в radix 5, для 5 ^ 30 возможностей; и 32 * 31 * 2 * 4 * 4 * 9 для позиций короля, цвета ходов, белых и черных прав на рокировку, квадрат прохода (из 8 вариантов плюс ни одного, девятый); это число 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 в пассивных кандидатах-жертвах (включая ни одного), и кодирование прав на замок и позиции короля внутри одного и того же набора с использованием прав на захват фактов имеет значение, только когда король находится на исходном поле. Это экономит 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-й бит: цвет ( 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, которые я даже не начал с en passant или рокировкой. Хорошо за мой предел ни с чем - даже не поворачивается. Вот где начинаются трюки.

Хорошо, вы видите эти типы выше? Епископ0 и Епископ1? Pawn0 и pawn1? Эти типы обозначены так, потому что они говорят нам немного вставить после этой части. Таким образом, Bishop0 означает, что после него будет 0, т. Е. Следующий кусок будет белым. Епископ1 говорит нам, что следующий кусок чёрный, а пешка0 и пешка1 работают одинаково. (Если этот кусок является последним из перечисленных, то он говорит нам о следующем ходу).

Мой худший случай включает в себя все фигуры на доске, поэтому с 16 пешками и 4 слонами это экономит мне 20 битов. Я до 173.

Хорошо. Для другого бита в моем худшем случае - когда есть 16 из кодированных цветов, мы прекращаем кодировать цвет - как мы знаем, это продвигается вперед. Мой худший случай теперь включает в себя белую фигуру, которая добирается до дальнего угла без захвата. Там я сохраняю только один бит. 172.

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

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

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

Рокировка.Чтобы произошла рокировка, ни король, ни соответствующая ладья не могли сдвинуться. Таким образом, когда ладья способна рокировать, она и король окажутся на своих местах. Таким образом, грачи, способные к рокировке, будут перечислены в том же месте, что и короли этого цвета. Поскольку это недопустимо (два короля или три короля одного цвета на доске) и может происходить только в трех возможных настройках для каждого цвета (слева, справа, оба ладьи указаны как короли) - дешифрирование совершенно возможно. Итак, без битов мы закодировали рокировку.

En Passant Здесь мы также будем использовать нелегальные позиции. Только одна пешка может быть в опасности за один раз. Должно быть в четвертом ряду. Уязвимая пешка будет «перевернута» обратно к своему домашнему ряду и переключена с тем, что там есть. Поскольку эта пешка находится в своем собственном первом ряду - недопустимая позиция, ситуация будет очевидна для декодера - она ​​поменяет позиции и пометит пешку как уязвимую для прохода.

Нам нужно было разобраться с заказом, потому что последний кусок должен быть «однозначно идентифицирован». В стандартном порядке мы не смогли бы определить, может ли ладья в заднем углу замкнуться - это неизвестно. Когда мы работаем извне, мы гарантируем, что где бы «ладья» не была «внесена в список», будь то в ее собственном углу или в середине доски, поскольку она была переключена с помощью уязвимой пешки en passant, будет фигура, перечисленная после это - так нам говорят тип ладьи. Мы знаем, что после него будет фигура, потому что пешка должна быть уязвимой, так как внутри нее должна быть пешка (что будет решительно закодировано позже в соответствии с инструкциями выше).

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

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

РЕДАКТИРОВАТЬ Я добавил код для (работающий?) Декодер - в 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 функции. Тот, который выполняет некоторое базовое разделение фигур и структуры доски, а также выясняет тип фигур и любые «неявные» части. Следующая функция заполняет структуру доски этими фигурами в несколько странном (и отличается от моего исходного алгоритма) порядке [объяснено в комментариях к коду]. Следующая функция берет заполненную доску и обнаруживает любые недопустимые позиции - затем она исправляет их и переименовывает пешек, которые уязвимы для en passant "x pawn-e" и любых ладей, которые могут замкнуть "x rook-c". Последняя функция - это обертка, которая выполняет эти функции по порядку и выдает на выходе как текущую доску, так и ход.

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


Это интересно. Я хотел бы видеть рабочую реализацию в качестве доказательства концепции.
Mego

Реализация, как правило, на несколько шагов выходит за рамки доказательства концепции, но я добавил декодер. Он находится в R и поэтому использует логические значения, а не биты (извините - не хотел использовать слишком много времени). Но я считаю, что это должно быть доказательством концепции.
user5957401

0

229/226 бит

Это оказывается не очень успешным, но может спасти других людей, идущих по тому же пути.

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

  • 1 немного за чью очередь
  • 4 биты для четырех возможностей рокировки
  • 3биты для en passant возможностей. Это имеет большую глубину, что я сначала понял. Пасс должен быть сделан пешкой, которая движется с того же ранга (ряда), что и захваченная пешка. Анализ случаев показывает, что, как только мы узнаем, сколько пешек цвета, который последний раз перешел, продвинулись ровно на два квадрата, будет не более 6 в пассивных случаях (включая случай, когда нет пешки, уязвимой для en passant ). В худшем случае это 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биты для en passant возможностей.
  • 6 биты для белого короля
  • lg 60 биты (наихудший случай) для черного короля
  • lg 63 биты (потому что я не хочу усложнять это до уровня проверки чеков) для белой королевы, используя позицию белого короля, если ее нет
  • Для каждой дополнительной белой королевы, 1немного сопровождаемой lg 62,lg 61 и т.д. биты для ее положения.
  • 0Бит.
  • lg 63 битов (или меньше, если бы были белые королевы) для черной королевы.
  • и т.п.

У n-го человека, который на самом деле присутствует, есть 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 триплета в форме (начало x, начало y, конец x, конец y), где каждый равен 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 and_m_ 3 = 564% 29 = 13. Наконец, g 5 = 19 // 29 = 0 и m 4 = 19% 29 = 19.

Так сколько битов используется для кодирования игры таким образом?

Для простоты, скажем, всегда есть 20 ходов за ход, а для наихудшего сценария мы всегда выбираем самый большой, 19. Полученное нами число составляет 19 m 20 м.

+ 19 ⋅ 20 м-1 + 19 ⋅ 20 м-2 + ⋯ + 19 ⋅ 20 + 19 = 20 м + 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 досок были разрешены пользователем для самостоятельного выбора, и не были ограничены требованием формирования шахматной игры.) Кроме того, игра в шахматы теоретически может занять много тысяч ходов , а ОП ясно о том, чтобы быть заинтересованным в худшем случае.
Андерс Касеорг

@AndersKaseorg: очень верно. Это действительно зависит от цели. Если вы пытаетесь сохранить всю игру со всеми остальными алгоритмами, потребуется m * c байтов, где m - количество ходов, а c - размер их вывода. Поэтому, если вы пытаетесь сохранить целую игру с 80 ходами, используя 160-битное решение, это займет 12800 бит, а мое - только 351. Ради соревнования я признаю, что вы правы, но я подумал, что это хорошее свойство чтобы отметить, так как очень часто хочется хранить целые игры, а не только доски.
edggy

Цель однозначна. «Цель состоит в том, чтобы сделать наименьшее представление шахматной доски, которую можно было бы использовать (после декодирования), чтобы определить все возможности перемещения для игрока на этом ходу. … Ваша оценка определяется наихудшим сценарием - максимально возможным размером в битах ».
Андерс Касеорг,

@AndersKaseorg: я никогда не утверждал, что это было неоднозначно. Я просто решил пойти другим путем. Стоит отметить, что для поиска наименьшей доски по моему алгоритму мне нужен наименьший путь, чтобы добраться до этой позиции. Например, в игре на терне 11741, которую вы связали, чтобы попасть на ту же позицию на доске, мне не нужно идти по этому пути, если все, что нам нужно, это доска. Поэтому, чтобы закодировать связанную игру, я просто нахожу самую короткую игру с двумя королями на тех клетках, которые могут быть только 200 ходами или меньше. Это можно сделать с помощью поиска в глубину.
edggy

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