Algorithm 两个整数的映射函数

Algorithm 两个整数的映射函数,algorithm,function,Algorithm,Function,所以 问题 我有两个整数,第一个是正整数,第二个是任意整数。我需要创建一个映射函数F,从它们到另一个整数值,它将是: 结果应该是整数值。对于第一种情况(x>0,y>0),为正整数值 对称的。这意味着F(x,y)=F(y,x) 独一无二。这意味着F(x0,y0)=F(x1,y1)(x0=x1^y0=y1)V(y0=x1^x0=y1) 我的方法 乍一看,对于正整数,我们可以使用F(x,y)=x2+y2这样的表达式,但这将失败——例如,对于第二种(常见)情况,892+232=132+912——这甚

所以

问题

我有两个整数,第一个是正整数,第二个是任意整数。我需要创建一个映射函数
F
,从它们到另一个整数值,它将是:

  • 结果应该是整数值。对于第一种情况(
    x>0
    y>0
    ),为正整数值
  • 对称的。这意味着F(x,y)=F(y,x)
  • 独一无二。这意味着F(x0,y0)=F(x1,y1)(x0=x1^y0=y1)V(y0=x1^x0=y1)
我的方法

乍一看,对于正整数,我们可以使用F(x,y)=x2+y2这样的表达式,但这将失败——例如,对于第二种(常见)情况,892+232=132+912——这甚至更复杂

用例

这在处理某些事情时可能很有用,这些事情应该是顺序独立的,并且需要是唯一的。例如,如果我们想要找到许多数组的笛卡尔积,并且我们想要结果是唯一的,独立于顺序,即
等于
。可通过以下方式完成:

function decartProductPair($one, $two, $unique=false)
{
   $result = [];
   for($i=0; $i<count($one); $i++)
   {
      for($j=0; $j<count($two); $j++)
      {
         if($unique)
         {
            if($i!=$j)
            {
               $result[$i*$i+$j*$j]=array_merge((array)$one[$i],(array)$two[$j]);
               //           ^
               //           |
               //           +----//this is the place where F(i,j) is needed
            }
         }
         else
         {
            $result[]=array_merge((array)$one[$i], (array)$two[$j]);
         }
      }
   }
   return array_values($result);
}
(通过发布示例,我想表明这个问题肯定与编程有关)

问题

如前所述,问题是-什么可以用作
F
?我想要尽可能简单的
F
。请记住两种情况:

  • 整数
    x>0
    y>0
    <代码>F(x,y)>0
  • 任意整数x,y,因此任意整数F(x,y)作为结果

可能是
F
不仅仅是一个表达式,而是一些为任何x,y找到所需结果的算法(因此也需要标记)。然而,表达式更好,因为它更像是能够在SQL或PHP或其他任何语言中使用该表达式。请随意编辑标记,因为我不确定这里的两个标记是否足够

您需要一个
MAX\u INTEGER
常量,并且结果将需要保持
MAX\u INTEGER**2
(比如:如果两个标记都是
int
,则都是
long
)。在这种情况下,其中一个功能是:

f(x,y)=min(x,y)*MAX_整数+MAX(x,y)

但我提出了一个不同的解决方案:使用字符串的哈希函数(比如md5),该字符串由str(min(x,y))、分隔符(比如“.”)和str(max(x,y))串联而成。即:

f(x,y)=md5(str(min(x,y))+“+str(max(x,y)))


它不是唯一的,但是碰撞是非常罕见的,并且对于大多数用例来说可能是正常的。如果仍然担心冲突,请将实际的{x,y}与f(x,y)一起保存,并检查是否发生了冲突。

对输入数字进行排序并交错其位:

x = 5
y = 3
Step 1. Sorting: 3, 5
Step 2. Mixing bits: 11, 101 -> 1_1_, 1_0_1 -> 11011 = 27
So, F(3, 5) = 27

最简单的解决方案:
f(x,y)=x^5+y^5

没有已知的正整数可以以多种方式写入两个五分之一幂的和。

现在,这是一个紧凑的表示形式是x*(x+3)/2+y*(x+1)+(y*(y-1))/2,它来自这样的排列:

    x->
y   0    1    3    6   10   15 
|   2    4    7   11   16
v   5    8   12   17
    9   13   18
   14   19   
   20

非有效(可能是巨大的数字),但正确的解决方案是:定义p_i=第i个素数。F(i,j)=p_i*p_j@Henrik我没有得到关于
F(x,y)={x,y}
(这是什么?)的答案——我发现左移位的有趣答案不适用,因为,很明显,整数溢出a=max(x,y),b=明显有什么问题:(a我如何保存大于maxint的值?记住,这不仅仅是理论问题-我需要将结果存储为整数值。我不想使用
md5
,因为结果应该是整数值不确定您使用的是什么语言,但是:(1)对
x
y
使用
int
,对结果使用
long
。或(2)如果您事先知道
x
y
值的某种阈值。否则,请使用散列。或者最后:使用具有任意精度的
bigint
类,并对
x
y
使用
int
。您能解释更多关于“交织位”的信息吗?也很有趣-负值呢?位的交错不是意味着需要更大的类型来保存结果吗?基本上所有的解决方案都是这样的,所以左移位(或我建议的乘法)也可以工作。正如@laune在对问题的评论中所说的。负数可能在计算f(x,y)之前映射为正数:
映射(x)=abs(x)*2+符号(x)
,其中符号(x)是0或1。@Nitzan Shaked++很明显,结果域的基数是N*N/2,其中N是F的操作数的域。F(0,27)=101000101=325这也很好。虽然理论上taxicab不是唯一的-这很合适,因为我确信integer远小于1E18+1,因为这很酷,我学到了一些新的东西。我认为OP想要一些他不能拥有的东西,以及适合
int
的解决方案(或者:与输入相同的数据类型)。这当然是不可能的,如果我们放弃这一要求,我会提出一个更好的(imho)解决方案。但是:就像。@nitzanshake实际上,左移位的解决方案会更合适,因为我可以处理16位整数(所以如果我将maxint声明为65535,我将得到整个longint的函数)-在这里,由于使用了5种电源,所以设置范围更窄。然而,这两种电源都非常好,但是对于OP暗示的任何用途来说,增长太快。
    x->
y   0    1    3    6   10   15 
|   2    4    7   11   16
v   5    8   12   17
    9   13   18
   14   19   
   20