【发布时间】:2023-02-23 12:15:43
【问题描述】:
给定一个任意长度和任意值的数组,写出一个方程式:'E' 以找到简化(压缩)表示:'R' 用于数组的随机输出:'O' 使得'R'被输入'E ' = 'O'。
例如;假设我们得到一个长度为 10 的数组作为输入,其中包含与其索引相关的值。
如果排序,数组将是 Array = [0,1,2,3,4,5,6,7,8,9]。
原始输入数组将是这些索引的一些随机顺序。让我们使用 Array = [9,5,8,2,1,0,6,3,4,7]。
找到“R”,当“R”应用于 [0,1,2,3,4,5,6,7,8,9] 时,“O”= [9,5,8,2,1, 0,6,3,4,7]。
只要输出“R”满足以下条件,我对任何语言的几乎任何解决此问题的方法都持开放态度。
#1。输出“R”在内存中比按字面存储索引数组小。
#2。输出“R”不仅仅是通过 LZ77 或 LZSS 之类的输入运行的直接压缩版本。输出“R”必须是随机顺序的新颖表示,而不是输入的导数。
#3。与输入相比,输出“R”的平均压缩比至少为 ~2:1。
#4。对于给定的数组长度,输出“R”在内存中具有恒定的固定大小。
详细来说,如果“R”需要 3 个字节的存储空间来重新创建 [9,5,8,2,1,0,6,3,4,7],那么期望 10 个元素的任何随机输入顺序都可以是使用 3 个字节存储在“R”中。 “R”的存储大小随数组大小线性增加是可以接受的。如果您找到不增加大小的解决方案,则可以加分。
作为起点,我对如何实现这一点的最佳猜测是使用随机数生成器作为“E”,将种子值作为“R”,这样你就可以得到输出“O”。困难在于种子值是未知变量,因此您必须向后工作才能从随机输入中找到它。我粗略地想象你会想要执行某种操作,如 Fisher-Yates shuffle(或等效)以从排序数组中重建“O”,然后计算出此操作的逆运算以从随机输入数组到一些种子值“R”。除了强制执行并检查每个种子值直到获得匹配之外,我不知道有什么数学方法可以完成此操作。 (这不是一个好的选择)。这就是为什么我说我对几乎所有解决方案都持开放态度,因为可能存在比使用随机数生成器更好的选择。但如果有的话,我不知道。
如果输出“R”有大小缩减的硬限制,那么对于非常小的数组长度,直接存储随机输入实际上更便宜,可以接受一些额外的余地。上面的例子只有 10 个元素长,因此已经相当小了。在实践中,需要这个解决方案来将长度的数组压缩到数十亿甚至更多。因此,如果您的解决方案“R”仅对于长度比“X”长的数组更小,那么它仍然是一个有效的解决方案,只要“X”是一个合理的数字,例如数百或数千而不是百万及以上。
最后提醒一下,我们不关心数组中包含的值,只关心索引。只有元素的顺序。出于所有意图和目的,我们可以假设输入数组中的每个值都是一个表示数组中其他索引的整数。
我认识到这是一个难题,因此感谢所有反馈和兴趣。预先感谢您的时间和贡献。
【问题讨论】:
-
我们能做的最好的事情就是对排列进行排序/取消排序,并以二进制形式对排序进行编码。通过斯特林近似 log(n!) = n log n - O(n),对于几乎所有 n,您都不会达到 2:1 的比率,甚至 (1+epsilon):1 对于任何常数 epsilon > 0。
标签: arrays algorithm random compression random-seed