В качестве альтернативного решения этой проблемы мой алгоритм использует составные дробные (нецелые) биты на карту для групп карт в колоде на основе количества оставшихся незаполненных рангов. Это довольно элегантный алгоритм. Я проверил мой алгоритм кодирования вручную, и он выглядит хорошо. Кодировщик выводит то, что представляется правильными цепочками битов (в байтовой форме для простоты).
Обзор моего алгоритма состоит в том, что он использует комбинацию групп карт и составное дробное кодирование битов. Например, в моем общем тестовом файле, состоящем из миллионов перемешанных колод, первая имеет первые 7 карт 54 A 236 Дж . Причина, по которой я выбрал 7- карточный размер блока, когда возможно 13 рядов карт, заключается в том, что 13 7 «рожков для обуви» (плотно прилегают) в 26 бит (так как 13 7 = 62 , 748 , 517 и 2 26 = 67 , 108 ,3754 A 236 J7131372613762 , 748 , 517226 ). В идеале мы хотим, чтобы эти 2 числа были как можно ближе (но с силой 2 числа немного выше), чтобы не тратить впустую больше, чем очень маленькую долю в процессе упаковки битов. Обратите внимание, что я мог бы также выбрать размер группы 4 при кодировании 13 рангов, поскольку 13 4 = 28 , 561 и 2 15 = 32 , 768 . Это не так туго припадоктак как +15 / 4 = 3,75 , но +26 / +7 = 3,71467 , 108 , 864241313428 , 56121532 , 76815 / 4 = 3,7526/7=3.714, Таким образом, число битов на карте несколько ниже , на карте , если мы используем способ упаковки.26/7
54A236J23456789TJQKA547131015,565,9752600111011011000010010010111
2615,565,9751354A236J7
13,12,11...,2,1)13,12,11...21312122125248,832218262,14418/53.61326/73.71455553333
Вот мой полный список затрат (количество бит на карту) для всех возможных количеств рангов:
13 26/7=3.714=3 5/7
12 18/5=3.600=3 3/5
11 7/2=3.500=3 1/2
10 10/3=3.333=3 1/3
9 16/5=3.200=3 1/5
8 3/1=3.000=3
7 17/6=2.833=2 5/6
6 13/5=2.600=2 3/5
5 7/3=2.333=2 1/3
4 2/1=2.000=2
3 5/3=1.667=1 2/3
2 1/1=1.000=1
1 0/1..4=0.0=0
75,6,7,7,7,7,KK1312713K21,2,3...3131720
16813,12,11
10777748747s. Если колода заканчивается парой (например, 77), тройной / сет (например, 777) или четверкой (например, 7777), мы получаем дополнительную экономию для этой колоды, используя мой алгоритм.
3222613163232
В первой колоде файла данных кодирование карточек выглядит следующим образом (схема будет представлена позже). Формат (размер группы, биты, режим кодирования ранга):
7,26,1372613
7,26,13
7,26,13
5,18,12
5,18,12
3,10,10
3, 9, 8
6,17, 7
5,13, 6
3, 5, 3
1, 0, 1
521683.23
181/33.23.254545454722772277...322223333444455556666777788889999TTTTJJJJQQQQKKKKAAAA40
1103,7K8101карта осталась. Это важно, потому что это делает процесс кодирования более эффективным, когда декодер может делать правильные предположения без необходимости передавать ему дополнительные сообщения.
313121110
54 A 236 J 87726 Q 3 3969 A A A Q J K 7 T 26 26 26 18 18 10 9 17 13 5 0
54A236J 87726Q3 3969AAA QJK7T 9292Q 36K J57 T8TKJ4 48Q8T 55K 4
13 12 xy 98 7 6 543 2 1 0
2166175168биты. Обратите внимание, что мы получили только один 4 в конце колоды, но если бы вместо этого мы получили все четыре 4, это лучший случай, и нам потребовалось бы только 161 бит для кодирования этой колоды, случай, когда упаковка фактически побеждает энтропия прямого двоичного кода его порядкового положения.
Теперь у меня есть код, реализованный для расчета требований к битам, и он показывает мне в среднем около 175 бит на деку с минимумом 155 и максимумом 183 для тестового файла с 3 миллионами колод. Таким образом, мой алгоритм использует 9 дополнительных бит на деку по сравнению с прямым двоичным кодированием метода порядкового положения. Не так уж плохо, только на 5,5% требуется дополнительное место для хранения. 176 бит это ровно 22 байта, так что это немного лучше, чем 52 байта на деку. Колода в лучшем случае (не показанная в тестовом файле с 3 миллионами колод) упаковывается в 136 битов, а колода в худшем случае (показанная в тестовом файле 8206 раз) составляет 183 бита. Анализ показывает, что наихудший случай - когда мы не получаем первый четырехугольник до тех пор, пока он не приблизится к (или не достигнет) 40-й карты. Затем, когда режим кодирования хочет быстро упасть, мы «застряли», заполняя блоки (размером до 7 карт) в более высокий режим кодирования битов. Кто-то может подумать, что не получить никаких квадов до 40-й карты было бы довольно редко, если использовать хорошо перемешанную колоду, но моя программа сообщает мне, что это произошло 321 раз в тестовом файле из 3 миллионов колод, так что это примерно 1 из каждых 9346 колод. Это чаще, чем я ожидал. Я мог бы проверить этот случай и обработать его с меньшим количеством битов, но это настолько редко, что это не повлияет на средние биты достаточно.
Также здесь есть кое-что еще очень интересное. Если я сортирую колоду по необработанным данным колоды, длина префиксов, которые повторяются значительное количество раз, составляет всего около 6 (например, 222244). Однако с упакованными данными эта длина увеличивается примерно до 16. Это означает, что если я отсортирую упакованные данные, я смогу получить значительную экономию, просто указав декодеру 16-битный префикс, а затем просто выведу оставшуюся часть колод (минус повторяющийся префикс), которые имеют тот же префикс, затем перейдите к следующему префиксу и повторите. Предполагая, что я сохраню даже 10 бит на колоду, я должен побить 166 бит на колоду. С техникой перечисления, заявленной другими, я не уверен, будет ли префикс таким же длинным, как в моем алгоритме. Также скорость упаковки и распаковки по моему алгоритму удивительно хороша.
Что касается 2-го уровня сжатия, где я сортирую выходные битовые строки моего алгоритма, а затем использую «разностную» кодировку: очень простой метод заключается в кодировании 61 278 уникальных 16-битных префиксов, которые отображаются как минимум дважды в выходных данных (и максимум 89 раз) просто в качестве начального бита 0 в выходных данных, чтобы указать декомпрессору 2-го уровня, что мы кодируем префикс (например, 0000111100001111), и затем любые упакованные колоды с таким же префиксом будут следовать с 1 начальным битом указать не префиксную часть упакованной колоды. Среднее количество упакованных колод с одинаковым префиксом составляет около 49 для каждого префикса, не считая нескольких уникальных (только одна колода имеет этот конкретный префикс). Похоже, я могу сэкономить около 15 бит на колоду, используя эту простую стратегию (сохраняя общие префиксы один раз).
После 2-го уровня сжатия с использованием разностного (префиксного) кодирования отсортированного вывода цепочки битов первого кодера я получаю около 160 бит на деку. Я использую префикс длины 18 и просто храню его без изменений. Поскольку почти все (245013 из 262144 = 93,5%) из этих возможных 18-битных префиксов отображаются, было бы еще лучше кодировать префиксы. Возможно, я могу использовать 2 бита, чтобы закодировать, какой тип данных у меня есть. 00 = обычный префикс 18 длины сохранен, 01 = «1 префикс up» (такой же, как предыдущий префикс, кроме 1 добавленного), 11 = прямое кодирование из упаковки 1-го уровня (в среднем около 175 бит). 10 = будущее расширение, когда я думаю о чем-то еще, чтобы кодировать, чтобы сохранить биты.
Кто-нибудь еще побил 160 бит на колоду? Я думаю, что смогу немного снизить мой уровень, экспериментируя и используя 2-битные дескрипторы, которые я упоминал выше. Возможно, он достигнет дна на 158-м. Моя цель - получить 156 бит (или лучше), потому что это будет 3 бита на карту или меньше. Очень впечатляюще. Много экспериментов, чтобы довести его до этого уровня, потому что если я изменю кодировку первого уровня, то мне придется повторно протестировать, которая является лучшей кодировкой 2-го уровня, и есть много комбинаций, которые можно попробовать. Некоторые изменения, которые я делаю, могут быть полезны для других подобных случайных данных, но некоторые могут быть смещены в сторону этого набора данных. Не совсем уверен, но если я получу желание, я могу попробовать другой набор данных из трех миллионов колод, чтобы посмотреть, что произойдет, если я получу аналогичные результаты на нем.
1050
У кого-нибудь есть идеи о том, как сделать мой алгоритм лучше, например, какие другие случаи я должен кодировать, чтобы уменьшить объем памяти для каждой колоды в среднем? Кто-нибудь?
Еще 2 вещи: 1) Я несколько разочарован тем, что больше людей не одобрили мое решение, которое, хотя и не является оптимальным по пространству, все же является приличным и довольно простым для реализации (у меня все работает нормально). 2) Я выполнил анализ своего файла данных с 3 миллионами колод и заметил, что наиболее часто встречающаяся карта с заполнением 1-го ранга (например, 4444) находится на карте 26. Это происходит примерно в 6,711% времени (для 201322 из 3 миллионов колод) ). Я надеялся использовать эту информацию, чтобы сжать больше, например, начать в режиме 12-символьного кодирования, так как мы знаем, что в среднем мы не видим каждый ранг до середины колоды, но этот метод не сжимал ни одного, поскольку его издержки превышали экономию. Я ищу некоторые изменения в моем алгоритме, которые могут реально сохранить биты.
Так есть ли у кого-нибудь идеи, что мне следует попробовать, чтобы сэкономить несколько бит на колоду, используя мой алгоритм? Я ищу паттерн, который встречается достаточно часто, чтобы я мог уменьшить количество бит на деку даже после дополнительных затрат на указание декодеру, какой паттерн ожидать. Я думал что-то с ожидаемой вероятностью оставшихся невидимых карт и складывал все оставшиеся одиночные карты в одно ведро. Это позволит мне быстрее перейти в режим более низкого кодирования и, возможно, сохранить некоторые биты, но я сомневаюсь в этом.
Кроме того, к вашему сведению, я сгенерировал 10 миллионов случайных перемешиваний и сохранил их в базе данных для удобства анализа. Только 488 из них заканчиваются квадом (например, 5555). Если я упаковываю только те, которые используют мой алгоритм, я получаю в среднем 165.71712 бит с низким 157 битам и высоким 173 битам. Чуть ниже 166 бит, используя другой метод кодирования. Я несколько удивлен тем, насколько редок этот случай (примерно 1 из каждых 20 492 тасовок в среднем).