从' n'的组合中生成唯一的数字。不同的数字?

时间:2014-04-29 13:34:10

标签: algorithm math numbers

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

我想从这个集合中生成一个数字(让我们调用生成的数字大' N')也是唯一的,这样我就可以验证一个数字' n1&# 39;属于集合' n'只需使用' N'

可能吗?

编辑:

感谢你们的答案,我正在调查他们。对于那些请求示例的人来说,这是一个简单的例子:

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

  

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

     

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

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

2 个答案:

答案 0 :(得分:4)

如果你处理的是小数字,没问题。每次编写数字时,你都用数字做同样的事情:数字是从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转换为undecimal(base11)33a44a27,并按数字分割' a'你可以将原始数字重新测试。

编辑:可变基数?

当然,这将在基数17(16位+分隔符)中以数字方式更好地工作。但我怀疑有更多的最佳方式,例如如果路径中的数字是唯一的,您添加的数字越多,剩余的越少,基数可缩小的越短。你能想象一个数字,其中第一个数字在基数为20,第二个数字在基数为19,第三个数字在基数为18,依此类推?可以这样做吗? MEH?

在这个变化的基础世界中(在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)+ ...

offset1:10-9 = 1 offset2:9 * 9 ^ 1-1 * 8 ^ 2 + 1 = 81-64 + 1 = 18 offset3: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);

所以N< = 102411会代表十个节点的任何路径?只是一个试验。你必须找到一种方法来命名它们,例如,如果它们是1,2,3,4,5,6 ...并且你使用5,你必须压缩其余的1,2,3,4,6- > 5,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。 Bloom过滤器没有假阴性(如果你说一个数字不在集合中,它确实不是),但确实遭受具有预期给定概率的误报(这取决于集合的大小) ,使用的函数数量和使用的位数。

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