Benim çözümüm: en iyi durum 7.025 bit / sayı, en kötü durum 14.193 bit / sayı, kaba ortalama 8.551 bit / sayı. Akış kodlu, rastgele erişim yok.
Ruslik'in cevabını okumadan önce bile, her sayı arasındaki farkı kodlamayı düşündüm, çünkü küçük olacak ve nispeten tutarlı olmalı, ancak çözüm aynı zamanda en kötü durum senaryosunu da barındırabilmelidir. Sadece 1000 sayı içeren 100000 sayılık bir alanımız var. Mükemmel bir şekilde tekdüze bir telefon rehberinde, her numara bir önceki sayıdan 100 ile daha büyük olacaktır:
55555-12 3 45
55555-12 4 45
55555-12 5 45
Durum buysa, bilinen bir sabit olduğu için sayılar arasındaki farklılıkları kodlamak için sıfır depolama gerekir. Ne yazık ki, sayılar 100'lük ideal adımlardan farklı olabilir. 100'lük ideal artıştan farkı kodlardım, böylece iki bitişik sayı 103 farklıysa, 3 sayısını kodlardım ve iki bitişik sayı 92 farklıysa, I -8 kodlayacaktır. Ben deltayı 100'lük ideal artıştan “ varyans ” olarak adlandırıyorum.
Varyans -99 (yani ardışık iki numara) ile 99000 arasında değişebilir (telefon defterinin tamamı 00000… 00999 sayılarından ve ek olarak en uzaktaki 99999 numaradan oluşur), bu 99100 olası değer aralığıdır.
Ben (gibi daha büyük farklılıkları karşılaşırsanız en yaygın farklılıkları kodlamak ve depolama genişletmek için minimal bir depolama tahsis amacı ediyorum Protobuf ‘ler varint). Yedi bitlik yığınlar, depolama için altı ve sonunda ek bir bayrak biti kullanacağım, bu varyansın mevcut olandan sonra en fazla üç parçaya kadar ek bir yığınla depolandığını belirtmek için (maksimum 3 * 6 = 262144 olası değer olan 18 bit depolama, olası varyansların sayısından (99100) daha fazladır. Yükseltilmiş bir bayrağı izleyen her ek öbek, daha yüksek öneme sahip bitlere sahiptir, bu nedenle ilk öbek her zaman 0- bit içerir 5, isteğe bağlı ikinci parçaların 6-11 bitleri ve isteğe bağlı üçüncü parçanın 12-17 bitleri vardır.
Tek bir yığın, 64 değeri barındırabilen altı bitlik depolama sağlar. Bu tek parçaya sığacak en küçük 64 varyansı eşlemek istiyorum (yani -32 ila +31 varyansları), bu nedenle -99 ila +98 varyanslarına kadar ProtoBuf ZigZag kodlamasını kullanacağım (çünkü buna gerek yok -99'un ötesinde negatif bir varyans için), bu noktada normal kodlamaya geçeceğim, 98 ile dengelenecek:
Varyans | Kodlanmış Değer
----------- + ----------------
0 | 0
-1 | 1
1 | 2
-2 | 3
2 | 4
-3 | 5
3 | 6
... | ...
-31 | 61
31 | 62
-32 | 63
----------- | --------------- 6 bit
32 | 64
-33 | 65
33 | 66
... | ...
-98 | 195
98 | 196
-99 | 197
----------- | --------------- ZigZag Sonu
100 | 198
101 | 199
... | ...
3996 | 4094
3997 | 4095
----------- | --------------- 12 bit
3998 | 4096
3999 | 4097
... | ...
262045 | 262143
----------- | --------------- 18 bit
Ek bir öbeği belirtmek için bayrak dahil, varyansların bit olarak nasıl kodlanacağına dair bazı örnekler:
Varyans | Kodlanmış Bitler
----------- + ----------------
0 | 000000 0
5 | 001010 0
-8 | 001111 0
-32 | 111111 0
32 | 000000 1 000001 0
-99 | 000101 1 000011 0
177 | 010011 1 000100 0
14444 | 001110 1 100011 1 000011 0
Dolayısıyla, örnek bir telefon rehberinin ilk üç numarası, aşağıdaki gibi bir bit akışı olarak kodlanacaktır:
BIN 000101001011001000100110010000011001 000110 1 010110 1 00001 0
PH # 55555-12345 55555-12448 55555-12491
POS 1 2 3
En iyi durum senaryosu , telefon defteri bir şekilde eşit olarak dağıtılmıştır ve varyansı 32'den büyük olan iki telefon numarası yoktur, bu nedenle sayı başına 7 bit artı başlangıç numarası için 32 bit toplam 32 + 7 * 999 olacaktır. = 7025 bit . 800 telefon numarası varyansının bir parçaya (800 * 7 = 5600), 180 numaranın her birine iki parçaya (180 * 2 * 7 = 2520) ve 19 numaranın her birine üç parçaya (20 * 3) sığdığı
karma bir senaryo * 7 = 399), artı ilk 32 bit toplam 8551 bittir .
En kötü senaryo , 25 sayı üç parçaya sığar (25 * 3 * 7 = 525 bit) ve kalan 974 sayı iki parçaya sığar (974 * 2 * 7 = 13636 bit), artı bir grand için ilk sayı için 32 bit toplamı14193 bit .
Kodlanmış sayıların miktarı |
1 parça | 2 parça | 3 parça | Toplam bit
--------- + ---------- + ---------- + ------------
999 | 0 | 0 | 7025
800 | 180 | 19 | 8551
0 | 974 | 25 | 14193
Gereken alanı daha da azaltmak için gerçekleştirilebilecek dört ek optimizasyon görebiliyorum:
- Üçüncü yığın yedi bitin tamamına ihtiyaç duymaz, sadece beş bit olabilir ve bayrak biti olmadan olabilir.
- Her yığın için en iyi boyutları hesaplamak için sayıların ilk geçişi olabilir. Belki belirli bir telefon defteri için, ilk öbekte 5 + 1 bit, ikinci 7 + 1 ve üçüncü 5 + 1 olması en uygun olacaktır. Bu, boyutu en az 6 * 999 + 32 = 6026 bit, artı 1 ve 2 parçalarının boyutlarını depolamak için üç bitlik iki sete (parça 3'ün boyutu gerekli 16 bitin geri kalanıdır) daha da düşürecektir. 6032 bit!
- Aynı başlangıç geçişi, varsayılan 100'den daha iyi beklenen bir artışı hesaplayabilir. Belki 55555-50000'den başlayan bir telefon rehberi vardır ve bu nedenle sayı aralığının yarısı olduğundan beklenen artış 50 olmalıdır. Ya da belki doğrusal olmayan dağılım (belki standart sapma) ve diğer bazı optimum beklenen artışlar kullanılabilir. Bu, tipik varyansı azaltabilir ve daha da küçük bir ilk parçanın kullanılmasına izin verebilir.
- Her bölüm kendi beklenen artışına ve yığın boyutu optimizasyonlarına sahip olacak şekilde, telefon rehberinin bölümlenmesini sağlamak için ilk geçişte daha fazla analiz yapılabilir. Bu, telefon rehberinin belirli yüksek oranda tekdüze bölümleri için daha küçük bir ilk yığın boyutuna (tüketilen bit sayısını azaltarak) ve tek tip olmayan parçalar için daha büyük parça boyutlarına (devam bayraklarında boşa harcanan bit sayısını azaltarak) izin verecektir.