尼姆乘法


17

背景

如果您进行大量代码打高尔夫球,则可能会意识到按位XOR操作。给定两个整数,它给出1两个输入不同的位中带有s的另一个整数。因此,例如1010 XOR 0011 = 1001

事实证明,它在博弈论中非常有用,在游戏理论中,它被称为“零和”。如果你有两场比赛的总和(也就是,你让在一场比赛中同时移动),该的位置是在每个单独的游戏的位置值的NIM总和。

但是我们可以更进一步。使用nim加法和适当的nim乘法定义,我们可以从非负整数形成一个字段。因此,挑战在于高尔夫nim乘法。

定义

Nim乘法遵循以下规则:
Fermat 2次方n =(2 ^(2 ^ k))且任何较小数字的nim乘积为普通乘积。
费马2幂n的尼姆乘积本身为3n / 2。
尼姆乘法分布在尼姆加法上。
Nim乘法是可交换的和关联的(如nim加法)。
乘法身份为1(加性身份为0)。

可以将任何非负整数表示为2的不同幂的nim和,并且可以将2的任意幂作为不同的Fermat数的乘积,因此这足以为所有非负整数定义nim乘法。

那都是非常抽象的,所以让我们来看一个例子。我将+用来表示nim加法(XOR)和*nim乘法。

6 * 13
= (4 + 2) * (8 + 4 + 1)
= (4 + 2) * ((4 * 2) + 4 + 1)
= (4 * 4 * 2) + (4 * 2 * 2) + (4 * 4) + (4 * 2) + (4 * 1) + (2 * 1)
= (6 * 2) + (4 * 3) + 6 + 8 + 4 + 2
= ((4 + 2) * 2) + 12 + 6 + 8 + 4 + 2
= (4 * 2) + (2 * 2) + 12 + 6 + 8 + 4 + 2
= 8 + 3 + 12 + 6 + 8 + 4 + 2
= 15

其他测试用例

4, 4 -> 6
4, 3 -> 12
4, 7 -> 10
2, 4 -> 8
2, 3 -> 1
1, 42 -> 42

挑战

编写一个程序或函数,以任意方便的形式给出两个非负整数,以计算它们的nim乘积。

这是,因此最短的提交将获胜。


1
如果读者不清楚,这与XOR(无进位)乘法不同,因此不是该挑战的重复。
xnor

1
OEIS中的Nim乘法表:A051775A051776A051910A051911
阿诺尔德

还要注意,没有直观的方法来理解木材倍增(根据那篇文章)。
user202729

费马数的形式为2 ^(2 ^ k)+1,因此您所说的费马数实际上少了一个。
凯利·洛德

@KellyLowder是的,这确实是Fermat 2的强大功能。

Answers:


8

Nim,120字节

proc f(a,b:int):int=
 var s={0..a*b}
 for i in 0..<a*b:s=s-{f(i%%a,i/%a)xor f(a,i/%a)xor f(i%%a,b)}
 for i in s:return i

在线尝试!

好的,这可能很疯狂,但是有人必须在Nim中进行Nim乘法...

这是维基百科的标准算法。问题是我不懂该语言,因此必须即时学习基础知识。尤其令我惊讶的是-=min它对集合不起作用,而设法提取最小值的最佳方法是使用迭代器并返回第一个值。希望Nim专家会帮助我改善这一点。


2
我想知道何时有人会尝试这个。


4

果冻,16字节

p’ß/;ß"^/ʋ€ṭ‘ḟ$Ṃ

使用递归公式xy = mex({ ay⊕xb⊕ab :a <x,b <y})进行乘数运算

在线尝试!

怎么运行的

p’ß/;ß"^/ʋ€ṭ‘ḟ$Ṃ  Main link. Left argument: x. Right argument: y.

p                 Cartesian product; yield the array of all pairs [a, b] such that
                  0 < a ≤ x and 0 < b ≤ y.
 ’                Decrement, changing the conditions to 0 ≤ a < x and 0 ≤ b < y.
          ṭ       Tack; yield [y, x].
        ʋ€        Combine the four links to the left into a dyadic chain. Call it
                  with right argument [y, x] and each of the [a, b] as left one.
  ß/                  Reduce [a, b] by the main link, computing the product ab.
     ß"               Zip [a, b] with [y, x] using the main link, computing the
                      array of products [ay, xb].
    ;                 Concatenate, yielding [ab, ay, xb].
       ^/             Reduce by bitwise XOR, yielding ab ⊕ ay ⊕ xb.
                  All that's left is to compute the minimum excluded (mex) non-
                  negative integer.
             $    Combine the two links to the left into a monadic chain.
           ‘          Increment the XOR sums.
            ḟ         Filterfalse; remove all incremented sums that appear in the
                      original sums.
              Ṃ  Take the minimum if the resulting array is non-empty or yield 0.
                 If x = 0 or y = 0, the array of sums is empty and Ṃ yields 0.
                 If x > 0 and y > 0, since 0 is among the sums, this finds the
                 smallest non-sum n+1 such that n ≥ 0 is a sum.
                 In either case, Ṃ yields xy.

4

CGSuite52 39 22字节

(a,b)->a.NimProduct(b)

没意识到它具有内置功能和匿名“程序”。

原始版本,36字节:

(a,b)->*a.ConwayProduct(*b).NimValue

或25个字节(如果输入/输出可能是零):

(a,b)->a.ConwayProduct(b)

好吧,我希望*a**b/ a*b可以工作,但是没有。


绝对是工作的正确工具。

3

Pyth,21个字节

Mf-TsmmxxgkdgkHgGdGH0

示范

使用nim乘法的最小排除元素公式,如此处所示

使用两个嵌套映射对所有较小的值(mm ... GH)进行迭代,然后将结果展平(s)。巧妙的部分附带f-T ... 0,其中我们从0开始向上遍历整数,以查找上述集合中未包含的第一个整数。通过这种方式,我们无需计算迭代上限,从而节省了几个字节。

最后,该函数g计算nim乘积。


3

的JavaScript(ES6),142个 128字节

f=(x,y,z=Math.log2,v=x&-x,t=z(x),u=z(y),s=t&u,r=s&-s)=>x<2|y<2?x*y:x>v?f(v,y)^f(x^v,y):y&y-1?f(y,x):r?f(f(x>>r,y>>r),3<<r-1):x*y
<div oninput=o.textContent=f(x.value,y.value)><input id=x><input id=y><pre id=o>

第一步是将x xyi的幂进行异或运算2,将其成对的nim乘积,然后对结果进行XOR(因为nim乘积分布在XOR上)。一旦我们回到了x和的情况y 2两个大国,我们注意到,费马大国乘相互使用普通的算术,所以我们可以因此factorise xy成费尔马权力。如果x并且y不分享费马的力量,我们可以逆转这一过程,简单地返回x * y。但是,如果它们共享一个费尔马功率,然后我们把两者xy用,权力,计算NIM的产品,然后采取NIM产品与费马电力的净息差平方。取消高尔夫:

function nimprod(x, y) {
    if (x < 2 || y < 2) return x * y;
    var v = x & -x;
    if (x > v) return nimprod(v, y) ^ nimprod(x ^ v, y); // nimprod distributes over ^
    if (y & (y - 1)) return nimprod(y, x); // x is a power of 2 but y is not
    var t = Math.log2(x);
    var u = Math.log2(y);
    var s = t & u;
    if (!s) return x * y; // x and y do not share a Fermat power
    var r = s & -s;
    return nimprod(nimprod(x >> r, y >> r), 3 << r - 1); // square the Fermat power
}

1

Wolfram语言(Mathematica),81个字节

x_±y_:=Min@Complement[Range[0,x*y],##&@@Array[BitXor[x±#2,#±y,±##]&,{x,y},0]]

在线尝试!

使用公式:

αβ=混合{αβ+αβ+αβα<αβ<β}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.