この問題の別の解決策として、私のアルゴリズムは、残っているランクの数に基づいて、デッキ内のカードのグループのカードごとに複合小数(非整数)ビットを使用します。かなりエレガントなアルゴリズムです。手作業でエンコードアルゴリズムを確認しましたが、見栄えは良いです。エンコーダは、正しいビット文字列と思われるものを出力します(簡単にするためにバイト形式で)。
私のアルゴリズムの概要は、カードのグループと複合フラクショナルビットエンコーディングの組み合わせを使用することです。たとえば、万枚のシャッフルデッキの共有テストファイルでは、最初のデッキには54 A 236 Jの最初の7枚のカードがあります。私が選んだ理由7と、カードブロックサイズを13枚のカードのランクが可能であるがためである13 7に"shoehorns"(ぴったりとフィット)26ビット(以降13 7 = 62 、748 、517及び2 26 = 67 、108 、3754 A 236 J7131372613762 、748 、517226)。理想的には、これらの 2つの数値をできる限り近づけて(ただし、2の累乗をわずかに高くする)、ビットパッキングプロセスでビットのごく一部を無駄にしないようにします。私もGROUPSIZE選択されている可能性に注意 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
だから、見て、我々は単に私たちのマスター「のそれらのランクの順序位置見上げる23456789 T J Q K A」ソートされたランクのリストを。たとえば、最初の実際のカードランク5は、ランクルックアップ文字列のルックアップ位置が4です。これらの7つのランク位置を、0から始まる13の基数として扱います(したがって、以前に取得した位置4は実際には3になります)。ベースに換算バック10(目的を確認するために)、我々が得る15 、565 、975。で2654 A 236 J23456789 TJQ KA547131015 、 565 、97526バイナリのビットはます。00111011011000010010010111
デコーダーは非常によく似た方法で機能します。これは、文字列は、(例えば)かかりバック小数ビットと変換し、(ベース10)を得るために15 、565 、975、次いで塩基に変換し、13それはランクを再構成、ランク検索文字列にオフセットを取得します一度に1枚ずつ、元の54 A 236 Jの最初の7枚のカードを受け取ります。ビットのブロックサイズは常に26ではありませんが、各デッキでは常に26から始まります。エンコーダーとデコーダーは両方とも、動作前でもデッキデータに関する重要な情報を持っています。これは、このアルゴリズムの非常に優れた点の1つです。2615 、565 、9751354 A 236J7
残りのランクのそれぞれ#(例えば、独自GROUPSIZEとコスト(カード当たりのビット#)を有しています。これらは、実験だけの力で遊んで発見された13 、12 、11 ...との力2。13個のランクが表示される場合のグループサイズの取得方法については既に説明しましたが、12個の未使用ランクにドロップするとどうなりますか?同じ方法。12の累乗を見て、そのうちの1つが2の累乗に非常に近くなるが、そのわずかに下になると停止します。 13 、12 、11 。。。、2 、1)13 、12 、 11 ...21312122 = 248 、832及び 2 18 = 262 、144。それはかなりきついフィットです。このグループを符号化するビット数である 18 / 5 = 3.6。で 13ランクグループはあった 26 / 7 = 3.714あなたが見ることができるように充填されていないランクの数が減少するにつれて、(ランクは以下のような充填され 5555、 3333、カードを符号化するビット数が減少します)。125248 、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 ...322223333444455556666777788889999 TTTTJJJJQ Q Q Q KKKKA A A A40
1103 、7K810ランクモードでは、おそらくそのデッキに使用するビット数を減らすことができます。いくつかのカードの特別な「グループ化された」バケツにあるカードの1つが表示されたら、その特別な「ランク」(実際のランクではなく、その特別なバケツに何かを見ただけのインジケータ)を出力します。バケット内のどのカードを見たかをデコーダに伝えるためにビットを追加します(グループがいっぱいになったため)。これを手動でトレースして、それを使用してビット節約が可能かどうかを確認します。エンコーダーとデコーダーの両方がカードをカウントし、どのランクがのみを持っているかを知るため、この特別なバケットを使用してあいまいさがないようにしてください。1カードが残っています。これは、エンコーダーが余分なメッセージを渡すことなく、デコーダーが正しい仮定を立てることができる場合、エンコードプロセスをより効率的にするため、重要です。
313121110
54 A 236 J 87726 Q 3 3969 A A A Q J K 7 T 9292 Q 36 K J 57 T 8 T K J 4 26 26 26 18 18 10 9 17 13 5 0
54 A 236 J 87726 Q 3 3969 A A A Q JK7 T 9292 Q 36 K J57 T 8 TKJ4 48 Q 8 T 55 K 4
13 12 x y 98 7 6 543 2 1 0
2166175168ビット。デッキの最後に1つの4しか持っていないことに注意してください。代わりに4つすべてを4つ持っていれば、それはより良いケースであり、そのデッキをエンコードするために161ビットだけが必要でした。序数位置のストレートバイナリエンコードのエントロピー。
ビット要件を計算するためのコードを実装しました。平均で、デッキあたり約175ビット、300万デッキのテストファイルで155の最低値と183の最高値を示しています。したがって、私のアルゴリズムは、デッキごとに9余分なビットを使用するように見えます。わずか5.5%の追加ストレージスペースが必要なだけで、それほど悪くはありません。176ビットは正確に22バイトであるため、デッキあたり52バイトよりもかなり優れています。ベストケースデッキ(300万デッキのテストファイルには表示されませんでした)は136ビットにパックされ、ワーストケースデッキ(テストファイルに8206回表示されました)は183ビットです。分析では、カード40に近づく(またはカード40になる)まで最初のクワッドが得られない場合が最悪のケースであることを示しています。その後、エンコードモードが急速に低下するため、高ビットエンコードモード。よくシャッフルされたデッキを使用して、カード40までクワッドを獲得しないのは非常にまれだと思うかもしれませんが、私のプログラムでは、300万デッキのテストファイルで321回発生したと言われています。それは私が予想していたよりも頻繁です。このケースをチェックして、より少ないビットで処理できますが、平均ビットに十分な影響を与えないほどまれです。
また、非常に興味深い何かがあります。生のデッキデータでデッキを並べ替えた場合、かなりの回数繰り返されるプレフィックスの長さは約6(222244など)だけです。ただし、パックされたデータでは、その長さが約16に増加します。つまり、パックされたデータを並べ替えると、デコーダに16ビットのプレフィックスを指定して残りのデッキを出力するだけで大幅な節約が得られるはずです。 (同じプレフィックスを除く)、同じプレフィックスがあり、次のプレフィックスに移動して繰り返します。この方法で1デッキあたり10ビットしか保存しないとすると、1デッキあたり166ビットを上回るはずです。他の人が述べた列挙手法では、プレフィックスがアルゴリズムの場合と同じかどうかはわかりません。また、私のアルゴリズムを使用したパッキングとアンパッキングの速度は驚くほど良好です。
アルゴリズムの出力ビット文字列を並べ替え、「差分」エンコーディングを使用する第2レベルの圧縮に関して:非常に簡単な方法は、出力データに少なくとも2回現れる最大61,278の一意の16ビットプレフィックスをエンコードすることです(最大報告された89回)単に出力の先頭ビット0として、プレフィクス(0000111100001111など)をエンコードしていることを第2レベルの解凍器に示し、その後、同じプレフィクスを持つパックされたデッキには、先頭に1ビットが続きますパックされたデッキの非プレフィックス部分を示します。同じプレフィックスを持つパックされたデッキの平均数は、各プレフィックスについて約49であり、一意の少数を含みません(その特定のプレフィックスを持つデッキは1つだけです)。この単純な戦略を使用して、デッキごとに約15ビットを節約できるようです(共通のプレフィックスを1回保存する)。
最初のエンコーダーのソートされたビットストリング出力の差分(プレフィックス)エンコードを使用した2番目のレベルの圧縮の後、デッキごとに約160ビットを取得しています。長さ18のプレフィックスを使用し、そのまま保存します。これらの可能な18ビットプレフィックスのほとんどすべて(262144のうち245013 = 93.5%)が表示されるため、プレフィックスをエンコードすることをお勧めします。おそらく、2ビットを使用して、所有しているデータのタイプをエンコードできます。00 =通常の長さの18プレフィックスを格納、01 =「1プレフィックスを追加」(1を追加することを除いて前のプレフィックスと同じ)、11 =第1レベルパッキングからのストレートエンコーディング(平均175ビット)。10 =ビットを節約するためにエンコードする他の何かを考えるときの将来の拡張。
他の誰かがデッキごとに160ビットを破ったか 上記で説明した2ビット記述子を使用し、実験を行うことで、少し低くなると思います。おそらく158ishで底を打つでしょう。私の目標は、156ビット(またはそれ以上)にすることです。カードあたり3ビット以下になるからです。非常に印象的。最初のレベルのエンコーディングを変更した場合、最高の2番目のレベルのエンコーディングである再テストを行う必要があり、試行する多くの組み合わせがあるため、そのレベルまで下げるための多くの実験があります。私が加えた変更は、他の同様のランダムデータには適している場合がありますが、このデータセットに偏っている場合もあります。確かではありませんが、もし衝動を得たら、別の300万デッキのデータセットを試して、同様の結果が得られたらどうなるかを確認できます。
1050
平均して各デッキのストレージのビットを削減する他のケースをエンコードする必要があるように、誰かが私のアルゴリズムを改善する方法についてアイデアを持っていますか?誰でも?
さらに2つのこと:1)より多くの人々が私のソリューションに賛成しなかったことに少しがっかりしています。これはスペース上は最適ではありませんが、まだまともで実装がかなり簡単です(私はうまくいきました)。2)私は300万デッキのデータファイルを分析し、1位が満たされる最も頻繁に発生するカード(4444など)がカード26にあることに気付きました。これは、時間の約6.711%に発生します(2013年の300万デッキ)。私はこの情報を使用して、12シンボルエンコードモードで開始するなど、さらに圧縮することを望んでいました。平均して、ミッドデッキについてはすべてのランクが表示されないことがわかっているためですが、この方法はオーバーヘッドが節約を超えるため、圧縮に失敗しました。実際にビットを節約できるアルゴリズムの調整を探しています。
だから誰も私のアルゴリズムを使用してデッキごとに数ビットを節約するために次にすべきことを考えていますか?デコーダに予想されるパターンを伝える余分なオーバーヘッドが発生した後でも、デッキあたりのビット数を減らすことができるように、頻繁に発生するパターンを探しています。目に見えない残りのカードの予想される確率で何かを考えていて、残りのすべての単一カードを単一のバケツにまとめました。これにより、私はより低いエンコードモードに素早くドロップし、おそらくいくつかのビットを節約できますが、私はそれを疑います。
また、参考までに、1,000万のランダムシャッフルを生成し、分析しやすいようにデータベースに保存しました。クワッドで終わるのはそのうちの488個(5555など)です。私のアルゴリズムを使用してそれらだけをパックすると、平均で157ビットの低ビットと173ビットの高ビットで165.71712ビットを取得します。他のエンコード方式を使用した166ビットよりわずかに下。私は、このケースの頻度が低いことに多少驚いています(平均で20,492シャッフルごとに約1)。