【问题标题】:Generate a unique number out of the combination of 'n' different numbers?从'n'个不同数字的组合中生成一个唯一的数字?
【发布时间】:2014-04-29 13:34:10
【问题描述】:

为了澄清,作为输入,我有 'n' (n1, n2, n3,...) 个数字(整数),例如每个数字在这个集合中都是唯一的。

我想从这个集合中生成一个数字(让我们将生成的数字称为大“N”),它也是唯一的,它允许我验证数字“n1”是否属于集合“n”通过使用“N”。

这可能吗?

编辑:

感谢大家的回答,我正在调查他们的atm。对于那些要求示例的人,这里是一个简单的示例:

想象一下我有那些具有随机唯一值(我们称之为标识符)的路径(双向图):

P1(N1):A----1----B----2----C----3----D

P2(N2):A----4----E----5----D

所以我想从知道 N1 的 A 获取完整路径(唯一路径,而不是所有路径),因此这条路径应该是 P1。 请注意,1,2,...只是此图中的唯一数字,而不是权重或距离,我只是将它们用于我的启发式。

【问题讨论】:

  • 你是怎么选的?随机?由您来选择吗?
  • 这是什么意思?你的问题不清楚。 Nn = {n1, n2, ...} 有什么关系?什么是“通过使用 N”(即使用 - 方式和地点)?等等
  • 这个问题可能有点未指定(并且还遗漏了您尝试过的内容),但我怀疑the pigeon-hole principle 阻止了这种可能性,假设这些数字都以相同的界限为界。跨度>
  • 现在我迷路了。 :) 这个例子中的数字是多少? A、B、C 或 1、2、3 或两者兼而有之?你想拯救什么?它们有多大?对了,A1B2C3D 还不是数字?
  • 唯一定义路径的数字必须与路径本身一样长(渐近,以位为单位)。所以这样做没有任何优势。

标签: algorithm math numbers


【解决方案1】:

如果您处理的是小数字,没问题。每次组成数字时,您都在用数字做同样的事情:数字是从 0 到 9 的数字,而完整的数字是它们的组合:

  • 本身就是一个数字
  • 对于给定的数字是唯一的
  • 让您轻松验证数字是否在里面

问题是数字必须有一个上限,例如 10 代表数字。为简单起见,我们假设 1000,类似的组合数可能是:

n1*1000^k + n2*1000^(k-1) + n3*1000^(k-2) ... + nk*1000^(0)

所以如果你有数字 33、44 和 27,你会得到:

33*1000000 + 44*1000 + 27,也就是数字N:33044027

当然你可以用更大的限制做同样的事情,像 256,1024 或 65535 这样的二进制,但它增长得很快。

如果可能的话,一个更好的主意是将其转换为带有一些分隔符的字符串(字符串仍然是数字!)(以 11 为底的数字,即 10 个普通数字 + 1 个分隔数字)。这更灵活,因为没有上限。想象一下使用数字 0-9 + 分隔数字“a”。您可以获得以 11 为底的数字 33a44a27。通过将其转换为以 10 为底或以 16 为底的数字,您可以获得一个普通的计算机编号(如果我猜对了,则为 65451833)。然后将 65451833 转换为 11 进制 (base11) 33a44a27,并按数字 'a' 拆分,即可得到原始数字进行测试。

编辑:可变基数?

当然,这在以 17 为基数(16 位+分隔符)的数字上会更好。但我怀疑有更优化的方法,例如如果路径中的数字是唯一的,你添加的数字越多,剩余的越少,基数就越短。你能想象一个数字,其中第一个数字以 20 为底,第二个数字以 19 为底,第三个数字以 18 为底,以此类推?这可以做到吗?嗯?

在这个变化的基础世界中(在 10 个节点图中),路径 n0-n1-n2-n3-n4-n5-n6-n7-n8-n9 将是

n0*10^0 + (n1*9^1)+(偏移量:1) + n2*8^2+(偏移量:18) + n3*7^3+(偏移量:170)+...

偏移量1:10-9=1 偏移量2:9*9^1-1*8^2+1=81-64+1=18 偏移量3:8*8^2-1*7^3+1=343-512+1=170

如果我做对了,在这个小提琴中:http://jsfiddle.net/Hx5Aq/ 最大的数字路径是:102411

var path="9-8-7-6-5-4-3-2-1-0"; // biggest number

o2=(Math.pow(10,1)-Math.pow(9,1)+1); // offsets so digits do not overlap
o3=(Math.pow(9,2)-Math.pow(8,2)+1);
o4=(Math.pow(8,3)-Math.pow(7,3)+1);
o5=(Math.pow(7,4)-Math.pow(6,4)+1);
o6=(Math.pow(6,5)-Math.pow(5,5)+1);
o7=(Math.pow(5,6)-Math.pow(4,6)+1);
o8=(Math.pow(4,7)-Math.pow(3,7)+1);
o9=(Math.pow(3,8)-Math.pow(2,8)+1);
o10=(Math.pow(2,9)-Math.pow(1,9)+1);
o11=(Math.pow(1,10)-Math.pow(0,10)+1);

var n=path.split("-");

var res;

res=
    n[9]*Math.pow(10,0) +
    n[8]*Math.pow(9,1) + o2 +
    n[7]*Math.pow(8,2) + o3 +
    n[6]*Math.pow(7,3) + o4 +
    n[5]*Math.pow(6,4) + o5 +
    n[4]*Math.pow(5,5) + o6 +
    n[3]*Math.pow(4,6) + o7 +
    n[2]*Math.pow(3,7) + o8 +
    n[1]*Math.pow(2,8) + o9 +
    n[0]*Math.pow(1,9) + o10;

alert(res);

所以 N5,7->6... => 1,2,3,4,5,6...(如果从第一个开始,则可以恢复且唯一)

【讨论】:

  • +1:这似乎是最直接和最有效的方法。
  • 感谢您的意见,这肯定会帮助我!
【解决方案2】:

理论上是的。

通过将 p_i 定义为第 i 个素数,您可以生成 N=p_(n1)*p_(n2)*....。现在,您所要做的就是检查是否有N%p_(n) == 0

但是,请注意N 会很快增长到庞大的数字,所以我不确定这是一个非常实用的解决方案。

一个非常实用的概率解决方案是使用bloom filters。请注意,布隆过滤器是一组位,可以轻松转换为任何数字N
布隆过滤器没有误报(如果您说某个数字不在集合中,它确实不是),但确实会以预期的给定概率(取决于集合的大小,使用的函数数和使用的位数)。

附带说明,要获得 100% 准确的结果,您至少需要 2^k 位(其中 k 是元素的范围)来表示数字 N通过将此数字视为位集,其中每个位表示集合中存在或不存在数字。您可以证明没有使用较少位的 100% 准确解决方案 (peigeon hole principle)。请注意,对于例如 32 位的整数,这意味着您将需要 2^32 位的 N,这是不切实际的。

【讨论】:

  • 你有疑问的感觉吗?对我竖起大拇指
猜你喜欢
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 2013-09-17
  • 2011-05-16
  • 1970-01-01
相关资源
最近更新 更多