การคูณ Nim


17

พื้นหลัง

หากคุณเล่นกอร์ดโค้ดมากคุณอาจทราบถึงการดำเนินการXOR ระดับบิต กำหนดจำนวนเต็มสองตัวมันให้จำนวนเต็มอีกตัวที่มี1s ในบิตที่อินพุตทั้งสองแตกต่างกัน ตัวอย่างเช่น1010 XOR 0011 = 1001.

ดูเหมือนจะมีประโยชน์มากในทฤษฎีเกมซึ่งเป็นที่รู้จักกันดีในชื่อ "nim sum" หากคุณมีผลรวมของสองเกม (นั่นคือคุณกำลังเคลื่อนไหวในเกมหนึ่งครั้ง) ค่าของตำแหน่งคือผลรวม nim ของค่าของตำแหน่งในแต่ละเกม

แต่เราสามารถก้าวไปอีกขั้น ด้วยการเพิ่ม nim และนิยามที่เหมาะสมของการคูณ nimเราสามารถสร้างเขตข้อมูลจากจำนวนเต็มที่ไม่ใช่ค่าลบ ดังนั้นความท้าทายคือการคูณกอล์ฟ

คำนิยาม

การทวีคูณของ Nim เป็นไปตามกฎต่อไปนี้:
ผลิตภัณฑ์ nim ของ Fermat 2-power n = (2 ^ (2 ^ k)) ที่มีจำนวนน้อยกว่าเป็นผลิตภัณฑ์สามัญ
ผลิตภัณฑ์ nim ของ Fermat 2-power n ด้วยตัวมันเองคือ 3n / 2
การทวีคูณของ NIM จะกระจายผ่านการเพิ่ม nim
การคูณ Nim คือการสลับและเชื่อมโยง (เช่นการเพิ่ม nim)
ข้อมูลเฉพาะตัวหลายตัวคือ 1 (และตัวตนเพิ่มเติมคือ 0)

จำนวนเต็มที่ไม่ใช่ค่าลบใด ๆ สามารถเขียนเป็นผลรวม nim ของพลังที่แตกต่างกันของสองและอำนาจใด ๆ ของสองสามารถเขียนเป็นผลิตภัณฑ์ของตัวเลขแฟร์มาต์ที่แตกต่างกันดังนั้นนี่คือเพียงพอที่จะกำหนด nim คูณสำหรับจำนวนเต็ม nonnegative ทั้งหมด

ตัวอย่าง

นั่นเป็นนามธรรมที่น่ารักดังนั้นเรามาดูตัวอย่างกัน ฉันจะใช้+เพื่อแสดงการเพิ่ม 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
Nim ตารางการคูณใน OEIS: A051775 , A051776 , A051910 , A051911
Arnauld

นอกจากนี้โปรดทราบว่าไม่มีวิธีที่เข้าใจง่ายในการเข้าใจการคูณด้วย nimber (อ้างอิงจากโพสต์นั้น)
user202729

หมายเลขแฟร์มาต์มีรูปแบบ 2 ^ (2 ^ k) +1 ดังนั้นสิ่งที่คุณกำลังโทรหาหมายเลขแฟร์มาต์นั้นมีค่าน้อยกว่า
Kelly Lowder

@ KellyLowder ใช่มันเป็นแฟร์มาต์ 2 แบบจริงๆ

คำตอบ:


8

สะเดา , 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ไม่ได้ผลสำหรับชุดและวิธีที่ดีที่สุดที่ฉันจัดการเพื่อหาสำหรับการสกัดขั้นต่ำคือการใช้ iterator และกลับค่าแรก หวังว่าผู้เชี่ยวชาญของ Nim จะช่วยฉันปรับปรุงสิ่งนี้


2
ฉันสงสัยว่าเมื่อไหร่จะมีคนลองทำสิ่งนี้


4

เยลลี่ขนาด 16 ไบต์

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

ใช้สูตรแบบเรียกซ้ำxy = mex ({ay ⊕ xb ⊕ ab: a <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 ไบต์หากอินพุต / เอาต์พุตอาจเป็น nimbers:

(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และyเป็นพลังแห่ง XOR ของ2ใช้ผลิตภัณฑ์ตามเข็มคู่ของพวกเขาแล้ว XOR ผลลัพธ์ (เพราะผลิตภัณฑ์ที่จำหน่าย NIM กระจายมากกว่า XOR) เมื่อเราย้อนกลับไปที่กรณีของxและyทั้งสองกำลังของ 2 เราจะทราบว่าพลังของแฟร์มาต์ทวีคูณซึ่งกันและกันโดยใช้เลขคณิตปกติดังนั้นเราจึงสามารถแยกตัวประกอบxและyเป็นพลังของแฟร์มาต์ได้ หากxและyไม่แบ่งปันพลังของแฟร์มาต์เราสามารถทำกระบวนการย้อนกลับและกลับมาx * yได้ อย่างไรก็ตามหากพวกเขาแบ่งปันพลังของแฟร์มาต์เราก็จะหารทั้งสองxและyด้วยพลังนั้นคำนวณหาผลิตภัณฑ์จากนั้นก็นำผลิตภัณฑ์ที่มีนิมกับกำลังกำลังสองของกำลังของแฟร์มาต์นั้น Ungolfed:

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]]

ลองออนไลน์!

ใช้สูตร:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.