Идеальная функция хеширования для платы 8 на 8? - PullRequest
1 голос
/ 29 ноября 2010

Я реализую плату только с двумя типами фигур и искал функцию для отображения с этой доски на длинное целое число (64 бита). Я думал, что это не должно быть так сложно, так как длинное целое число содержит больше доступной информации, чем массив 8 на 8 (назовите его grid [x] [y]) с только 3 возможными элементами в каждом месте, включая пустой элемент. Я попробовал следующее:
(1) Зобрист хэширует с помощью Longs, а не int (просто для проверки - я не ожидал, что это сработает идеально)
(2) Перевести сетку в 64-символьную строку из базового числа 3, а затем взяла это число и проанализировала его в long. Я думаю, что это должно работать, но это заняло очень много времени.
Есть ли более простое решение (2), включающее битовые операции сдвига или что-то в этом роде?
Изменить: Пожалуйста, не дайте мне фактический код, так как это для проекта класса, и это, вероятно, будет считаться неэтичным в нашем отделе (или, по крайней мере, не в Java).
Edit2: в основном, на доске в каждый момент времени есть только 10 белых и 10 черных, из которых две фигуры одного цвета не могут быть соседями в горизонтальном, вертикальном или диагональном направлении. Кроме того, есть 12 мест для каждого цвета, где только этот цвет может поместить кусочки.

Ответы [ 4 ]

2 голосов
/ 29 ноября 2010

Если каждая плитка в игре может иметь одно из трех состояний в любой момент игры, то минимальный объем памяти, необходимый для «идеального хеширования» при хешировании всех возможных состояний игровой доски, в любой данный моментбудет
= мощность (3,8 * 8) отдельных хешей
= log2 (3 ^ 64) биты
= прибл.101,4 бита, поэтому вам понадобится как минимум 102 бита для хранения этой информации

На этом этапе вы можете просто сказать, что для каждой плитки есть 4 состояния, что приведет к необходимости 128 бит .

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

Например (написанный как c ++, может потребоваться изменить код, еслиплатформа не поддерживает 128-битные числа) uint_128 CreateGameBoardHash(int (&game_board)[8][8]) { uint_128 board_hash = 0; for(int i = 0; i < 8; ++i) { for(int j = 0; j < 8; ++j) { board_hash |= game_board[i][j] << ((i * 8 + j) *2); } } return board_hash; }

Этот метод будет тратить только 26 бит (чуть более 3 байтов) на оптимальное решение из 102 бит, но вы сэкономите МНОГО времени обработки, котороеиначе было бы потрачено на математику с основанием 3.


Edit Вот версия, которая не требует 128 бит и должна работать на любом 16-битном (или лучше) процессоре struct GameBoardHash { uint16 row[8]; };</p> <p>GameBoardHash CreateGameBoardHash(int (&game_board)[8][8]) { GameBoardHash board_hash; for(int i = 0; i < 8; ++i) { board_hash.row[i] = 0; for(int j = 0; j < 8; ++j) { board_hash.row[i] |= game_board[j] << (j*2); } } return board_hash; }

0 голосов
/ 29 ноября 2010

Как насчет 16-байтового массива, содержащего биты? Каждые 2 бита представляют значение позиции, поэтому, учитывая позицию на доске 8x8 (pos = 0-63), вы можете вычислить индекс, разделив pos на 4, и вы можете получить значение, выполнив битовую манипуляцию, чтобы получить два бита (бит0 = pos mod 4 и бит1 = бит0 + 1). Два бита могут быть 00, 01 или 10.

0 голосов
/ 29 ноября 2010

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

Сделайте это проще для себя ... Сделайте некоторый хеш для вашей позиции в перезаписи для GetHashCode (), а затем выполните остальную работу в функции Equals.*

Если вам ДЕЙСТВИТЕЛЬНО нужно, чтобы оно было идеальным, то вам нужно использовать GUID для кодирования ваших данных и создать свой собственный хэш, который может использовать 128-битные ключи.Но это просто огромная трата времени на небольшую выгоду.

0 голосов
/ 29 ноября 2010

Это не вписывается в 64-битное целое число.У вас есть 64 квадрата, и вам нужно больше 1 бита для записи каждого квадрата.Зачем вам это нужно, чтобы вписаться в 64-битный Int?Вы нацеливаетесь на ZX81?

...