Nim Çarpma


17

Arka fon

Çok sayıda kod golfü yaparsanız, muhtemelen bitsel XOR işleminin farkındasınızdır . İki tamsayı 1verildiğinde, iki girişin farklı olduğu bitlerde s ile başka bir tamsayı verir . Yani, örneğin 1010 XOR 0011 = 1001,.

"Nim sum" olarak bilinen oyun teorisinde çok faydalı olduğu ortaya çıktı. İki oyunun toplamına sahipseniz (yani, bir seferde bir oyunda hamle yapıyorsunuz), pozisyonun değeri , her bir oyundaki pozisyonların değerlerinin nim toplamıdır.

Ama bunu bir adım daha ileri götürebiliriz. Nim ilavesi ve nim çarpımının uygun bir tanımı ile , negatif olmayan tamsayılardan bir alan oluşturabiliriz. Bu yüzden zorluk golf nim çarpma.

Tanım

Nim çarpımı aşağıdaki kurallara uyar:
Fermat 2-power n = (2 ^ (2 ^ k)) nim ürünü daha küçük bir sayı ile normal üründür.
Kendisiyle birlikte bir Fermat 2-power n'nin nim ürünü 3n / 2'dir.
Nim çarpımı, nim ilavesine göre dağılır.
Nim çarpımı değişmeli ve birleştiricidir (nim ilavesi gibi).
Çarpıcı kimlik 1'dir (ve ek kimlik 0'dır).

Herhangi bir negatif olmayan tamsayı, ikisinin farklı güçlerinin nim toplamı olarak yazılabilir ve ikinin herhangi bir gücü, farklı Fermat sayılarının ürünü olarak yazılabilir, bu nedenle tüm negatif olmayan tamsayılar için nim çarpımını tanımlamak için yeterlidir.

Misal

Hepsi oldukça soyuttu, bu yüzden bir örnek üzerinde çalışalım. Ben +nim ilavesi (XOR) ve *nim çarpımı için kullanacağım .

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

Ek Test Durumları

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

Meydan okuma

Herhangi bir uygun biçimde iki negatif olmayan tam sayı verildiğinde, nim ürünlerini hesaplayan bir program veya işlev yazın.

Bu , çok kısa teslim kazanır.


1
Okuyucular için net değilse, bu XOR (taşımasız) çarpımından farklıdır ve bu yüzden bu zorluğun bir kopyası değildir.
xnor

1
OEIS'te Nim çarpım tabloları: A051775 , A051776 , A051910 , A051911 .
Arnauld


Fermat numaraları 2 ^ (2 ^ k) +1 biçimindedir, bu nedenle Fermat numarası olarak adlandırdığınız şey aslında bir tane daha azdır.
Kelly Lowder

@KellyLowder Evet, bu gerçekten bir Fermat 2 gücü.

Yanıtlar:


8

Nim , 120 bayt

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

Çevrimiçi deneyin!

Tamam, bu çılgınca olabilir, ama biri Nim'de Nim çarpımı yapmak zorundaydı ...

Bu Wikipedia'nın standart algoritmasıdır. Sorun şu ki, dili bilmiyorum, bu yüzden anında temelleri öğrenmek zorunda kaldım. Özellikle, şaşırdım -=ve minsetler için işe yaramadı ve minimumları çıkarmak için bulmanın en iyi yolu, yineleyiciyi kullanmak ve ilk değeri döndürmekti. Umarım, Nim uzmanları bunu geliştirmeme yardımcı olur.


2
Birinin bunu ne zaman deneyeceğini merak ediyordum.


4

Jöle , 16 bayt

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

Çevik çarpma için xy = mex ({ay ⊕ xb ⊕ ab: a <x, b <y}) özyinelemeli formülünü kullanır .

Çevrimiçi deneyin!

Nasıl çalışır

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 bayt

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

Bu yerleşik ve anonim "prosedürler" olduğunu fark etmedi.

Orijinal sürüm, 36 bayt:

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

Veya giriş / çıkış kenarları olabilirse 25 bayt:

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

/Ey, ümit ediyorum *a**b/ çalýţtým a*b, ama öyle deđil.


Kesinlikle iş için doğru araç.

3

Pyth , 21 bayt

Mf-TsmmxxgkdgkHgGdGH0

gösteri

Burada verildiği gibi, nim çoğalmasının minimum hariç tutulan eleman formülasyonunu kullanır .

Tüm küçük değerler üzerinde yineleme yapmak için iki iç içe harita kullanılır (mm ... GH ) , ardından sonuçlar düzleştirilir ( s). Zeki kısım f-T ... 0, yukarıda belirtilen sette bulunmayan ilk parçayı bulmak için 0'dan tamsayılara kadar yinelediğimiz kısım ile birlikte gelir . Bunu yaparak, birkaç bayt tasarruf ederek bir yineleme üst sınırını hesaplamamız gerekmez.

Sonunda, fonksiyon gnim ürününü hesaplar.


3

JavaScript (ES6), 142 128 bayt

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>

İlk adım, hem bölmek olduğunu xve yyetkilerinin bir XOR içine 2nim ürünler ve sonra XOR sonuçları (XOR üzerinde nim ürün dağıtımların çünkü), onların çiftler halinde alır. Biz davasıyla recursed sonra xve y2 her iki güçlerin, biz unutmayın çarpın birbirlerini kullanarak sıradan aritmetik ile Fermat güçler, bu yüzden biz bu nedenle Factorise xve yFermat güçler içine. Eğer xve ybir Fermat gücünü paylaşmayan biz süreci tersine çevirmek ve sadece dönebilir x * y. Ancak bir Fermat gücünü paylaşıyorlarsa, o zaman ikisini de böleriz xve ynim ürününü hesaplarız, nim ürününü bu Fermat gücünün nim karesiyle birlikte alırız. 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 Dili (Mathematica) , 81 bayt

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

Çevrimiçi deneyin!

Formülü kullanarak:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.