님 곱셈


17

배경

많은 코드 골프를한다면, 비트 XOR 연산을 알고있을 것 입니다. 두 개의 정수가 주어지면 두 1입력이 다른 비트에서 s를 갖는 또 다른 정수를 제공합니다 . 예를 들어 1010 XOR 0011 = 1001.

그것은 "nim sum"으로 더 잘 알려진 게임 이론에서 매우 유용한 것으로 판명되었습니다. 당신이 (즉, 당신이 한 번에 하나의 게임에서 이동을 만들고 있어요)이 개 게임의 합이있는 경우 위치의 각 개별 게임에서 위치 값의 NIM 합계입니다.

그러나 우리는 이것을 한 단계 더 발전시킬 수 있습니다. nim 추가와 nim 곱셈 의 적절한 정의 를 사용하면 음이 아닌 정수에서 필드를 형성 할 수 있습니다. 따라서 도전은 골프 nim 곱셈입니다.

정의

Nim 곱셈은 다음 규칙을
따릅니다. 숫자가 더 작은 Fermat 2-power n = (2 ^ (2 ^ k))의 nim 곱은 일반 곱입니다.
Fermat 2-power n 자체의 nim 곱은 3n / 2입니다.
님 곱셈은 님 추가에 분포합니다.
님 곱셈은 계산적이고 연관성이 있습니다 (nim 추가와 동일).
곱셈 항등은 1입니다 (첨가 항등도는 0).

음이 아닌 정수는 2의 고유 거듭 제곱의 nim sum으로 쓸 수 있고, 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 product를 계산하는 프로그램이나 함수를 작성하십시오.

이것은 이므로 가장 짧은 제출이 이깁니다.


1
독자들에게 명확하지 않은 경우, 이것은 XOR (carryless) 곱셈과 다르므로 그 도전과 중복되지 않습니다.
xnor

1
OEIS의 Nim 곱셈표 : A051775 , A051776 , A051910 , A051911 .
Arnauld


Fermat 번호는 2 ^ (2 ^ k) +1 형식이므로 Fermat 번호라고 부르는 것은 실제로 1이 적습니다.
Kelly Lowder

@KellyLowder 네, 정말 Fermat 2의 힘입니다.

답변:


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 곱셈을해야했습니다 ...

Wikipedia의 표준 알고리즘입니다. 문제는 언어를 모르기 때문에 즉석에서 기본을 배워야한다는 것입니다. 특히, 나는 놀랐다 -=min설정을 위해 작동하지 않았다, 나는 최소를 추출 찾기 위해 관리하는 가장 좋은 방법은 반복자를 사용하여 첫 번째 값을 반환하는 것이 었습니다. Nim 전문가가이를 개선 할 수 있기를 바랍니다.


2
누군가가 이것을 시도 할 때 궁금합니다.


4

젤리 , 16 바이트

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

사용하는 재귀 공식 XY = MEX ({AY ⊕ XB ⊕ AB하십시오 <x, B <Y}) 에 대한 nimber 승산 .

온라인으로 사용해보십시오!

작동 원리

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

CGSuite ,52 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

데모

여기에 주어진대로 최소 배제 된 요소 곱셈의 최소값을 사용합니다 .

두 개의 중첩 된 맵을 사용하여 더 작은 모든 값을 반복하고 ( mm ... GH) 결과를 평평하게합니다 ( s). 영리한 부분은와 함께 제공되며 f-T ... 0여기서 0에서 위쪽으로 정수를 반복하여 위에서 언급 한 세트에 포함되지 않은 첫 번째 정수를 찾습니다. 이 방법으로 반복 바이트 상한을 계산할 필요가 없으므로 몇 바이트를 절약 할 수 있습니다.

결국이 함수 g는 nim 곱을 계산합니다.


3

자바 스크립트 (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>

첫 번째 단계는 둘을 분할하는 xy의 멱수의 XOR로 2NIM 제품, 그리고 XOR 결과 (XOR 위에 NIM 제품에 분배로 인해), 그 짝을. 우리의 경우에에 반복하면 xy2 모두의 힘, 우리는 참고 곱셈을 사용하여 서로 일반 산술 페르마의 힘, 그래서 우리가 할 수 있으므로 factorise xy페르마의 힘으로. 경우 xy페르마의 전원을 공유하지 않는 우리는 과정을 역 간단하게 반환 할 수 있습니다 x * y. 그러나 그들이 페르마 힘을 공유한다면, 우리는 둘 다 xy그 힘으로 나눠서 nim 곱을 계산 한 다음 nim product를 그 Fermat power의 nim square로 취합니다. 언 골프 드 :

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 Language (Mathematica) , 81 바이트

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

온라인으로 사용해보십시오!

공식 사용하기 :

αβ=멕스({α'β+αβ'+α'β':α'<α,β'<β}).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.