【问题标题】:Optimal way to compress 60 bit string压缩 60 位字符串的最佳方法
【发布时间】:2021-01-26 08:09:09
【问题描述】:

给定 15 个随机十六进制数(60 位),其中每 20 位运行总是至少有 1 个重复(5 个十六进制)。

压缩字节的最佳方式是什么?

这里有一些例子:

01230 45647 789AA
D8D9F 8AAAF 21052
20D22 8CC56 AA53A
AECAB 3BB95 E1E6D
9993F C9F29 B3130

最初我一直在尝试仅在 20 位上使用 Huffman 编码,因为 Huffman 编码可以从 20 位下降到 ~10 位,但存储表需要超过 9 位。

这是显示 20 位的细分 -> 01230 的 10 位

Character   Frequency   Assignment  Space Savings
0           2           0           2×4 - 2×1 = 6 bits
2           1           10          1×4 - 1×2 = 2 bits
1           1           110         1×4 - 1×3 = 1 bits
3           1           111         1×4 - 1×3 = 1 bits

然后我尝试对所有 300 位(5 个 60 位运行)进行霍夫曼编码,这是上面示例中给出的映射:

Character   Frequency   Assignment  Space Savings
---------------------------------------------------------
a           10          101         10×4 - 10×3 = 10 bits
9           8           000         8×4 - 8×3 = 8 bits
2           7           1111        7×4 - 7×4 = 0 bits
3           6           1101        6×4 - 6×4 = 0 bits
0           5           1100        5×4 - 5×4 = 0 bits
5           5           1001        5×4 - 5×4 = 0 bits
1           4           0010        4×4 - 4×4 = 0 bits
8           4           0111        4×4 - 4×4 = 0 bits
d           4           0101        4×4 - 4×4 = 0 bits
f           4           0110        4×4 - 4×4 = 0 bits
c           4           1000        4×4 - 4×4 = 0 bits
b           4           0011        4×4 - 4×4 = 0 bits
6           3           11100       3×4 - 3×5 = -3 bits
e           3           11101       3×4 - 3×5 = -3 bits
4           2           01000       2×4 - 2×5 = -2 bits
7           2           01001       2×4 - 2×5 = -2 bits

这总共节省了 8 位,但 8 位不足以存储霍夫曼表。似乎由于数据的随机性,您尝试使用霍夫曼编码的位数越多,它的效果就越差。霍夫曼编码似乎在 20 位(减少 50%)时效果最好,但在 AFAIK 中以 9 位或更少位存储表格是不可能的。


在 60 位字符串的最坏情况下,仍然至少有 3 个重复,平均情况下有超过 3 个重复(我的假设)。由于至少 3 次重复,在 60 位运行中最多可以拥有的符号只有 12 个。

由于重复加上不到 16 个符号,我不禁觉得可以使用某种类型的压缩

【问题讨论】:

  • @MarkAdler 我用01230 将 20 位转换为 10 位的示例更新了问题。 10 位只是编码,不包括表格(否则这似乎会打破香农限制)
  • 您是要压缩 60 位还是 60*N 位?

标签: compression huffman-code entropy information-theory


【解决方案1】:

如果我简单地计算至少两个十六进制数字相等的 20 位值的数量,则有 524,416 个。略多于 219。因此,您最多可以节省 20 个中的一小部分。

似乎不值得。

【讨论】:

    【解决方案2】:

    如果我把你的问题分成两部分:

    1. 如何压缩(完美)随机数据:你不能。每一点都是一些新的熵,压缩算法无法“猜到”。
    2. 如何压缩“五个字符中的一个重复”:重复可以有 10 个选项(见下表)。这基本上是熵。只需存储它是哪个选项(可能为整行分组)。

    这些是选项:

    AAbcd = 1    AbAcd = 2    AbcAd = 3    AbcdA = 4    (<-- cases where first character is duplicated somewhere)
                 aBBcd = 5    aBcBd = 6    aBcdB = 7    (<-- cases where second character is duplicated somewhere)
                              abCCd = 8    abCdC = 9    (<-- cases where third character is duplicated somewhere)
                                           abcDD = 0    (<-- cases where last characters are duplicated)
    

    所以对于你的第一个例子:

    01230 45647 789AA
    

    第一个(01230)是选项4,第二个是3,第三个是0

    您可以通过将每个连续乘以 10 来压缩它:(4*10 + 3)*10 + 0 = 430 并使用除法和取模解压缩:430%10=0, (430/10)%10=3, (430/10/10)%10=4。所以你可以这样存储你的号码:

    1AE 0123 4567 789A
    ^^^ this is 430 in hex and requires only 10 bit
    

    三个选项组合的最大数量是1000,所以10位就足够了。

    与通常存储这 3 个字符相比节省 2 位。正如其他人已经评论过的那样 - 这可能不值得。整条生产线甚至更少:2 位 / 60 位 = 节省 3.3%。

    【讨论】:

    • 谢谢,这项技术非常聪明,正是我正在寻找的那种直觉
    【解决方案3】:

    如果您想先删除重复项,请执行此操作,然后查看页面底部的链接。如果您不想删除重复项,则仍然查看页面底部的链接:

    Array.prototype.contains = function(v) {
      for (var i = 0; i < this.length; i++) {
        if (this[i] === v) return true;
      }
      return false;
    };
    
    Array.prototype.unique = function() {
      var arr = [];
      for (var i = 0; i < this.length; i++) {
        if (!arr.contains(this[i])) {
          arr.push(this[i]);
        }
      }
      return arr;
    }
    
    var duplicates = [1, 3, 4, 2, 1, 2, 3, 8];
    var uniques = duplicates.unique(); // result = [1,3,4,2,8]
    
    console.log(uniques);
    

    那么您将缩短您必须处理的代码。那你可能想看看Smaz

    Smaz 是一个适合压缩字符串的简单压缩库。

    如果这不起作用,那么你可以看看这个:

    http://ed-von-schleck.github.io/shoco/

    Shoco 是一个用于压缩和解压缩短字符串的 C 库。它非常快速且易于使用。默认压缩模型针对英文单词进行了优化,但您可以根据您的特定输入数据生成自己的压缩模型。

    让我知道它是否有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      • 2023-03-30
      • 2021-01-13
      相关资源
      最近更新 更多