Moltiplicazione di Nim


17

sfondo

Se fai molto golf a codice, probabilmente sei a conoscenza dell'operazione XOR bit a bit . Dati due numeri interi, fornisce un altro numero intero con 1s nei bit in cui i due ingressi differiscono. Quindi, per esempio 1010 XOR 0011 = 1001,.

Risulta essere molto utile nella teoria dei giochi, dove è meglio conosciuto come "nim sum". Se hai la somma di due partite (ovvero fai mosse in una partita alla volta), il valore della posizione è la somma nim dei valori delle posizioni in ogni singola partita.

Ma possiamo fare un ulteriore passo avanti. Con l'aggiunta di nim e una definizione appropriata della moltiplicazione di nim , possiamo formare un campo dagli interi non negativi. Quindi la sfida è la moltiplicazione del golf nim.

Definizione

La moltiplicazione Nim obbedisce alle seguenti regole:
Il prodotto nim di un Fermat 2-power n = (2 ^ (2 ^ k)) con un numero inferiore è il prodotto ordinario.
Il prodotto nim di un Fermat 2-power n con se stesso è 3n / 2.
La moltiplicazione Nim si distribuisce sull'aggiunta NIM.
La moltiplicazione Nim è commutativa e associativa (come lo è aggiunta nim).
L'identità moltiplicativa è 1 (e l'identità additiva è 0).

Qualsiasi numero intero non negativo può essere scritto come la somma nim di poteri distinti di due, e qualsiasi potere di due può essere scritto come il prodotto di numeri Fermat distinti, quindi questo è sufficiente per definire la moltiplicazione nim per tutti i numeri interi non negativi.

Esempio

Era tutto piuttosto astratto, quindi esaminiamo un esempio. Userò +per indicare l'addizione nim (XOR) e *per la moltiplicazione 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

Casi di prova aggiuntivi

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

Sfida

Scrivi un programma o una funzione che, dati due numeri interi non negativi in ​​qualsiasi forma conveniente, calcola il loro prodotto nim.

Si tratta di , quindi vince l'invio più breve.


1
Nel caso in cui non sia chiaro per i lettori, questo è diverso dalla moltiplicazione XOR (senza borsa), e quindi non è un duplicato di quella sfida.
xnor

1
Tabelle di moltiplicazione Nim in OEIS: A051775 , A051776 , A051910 , A051911 .
Arnauld


I numeri Fermat sono nel formato 2 ^ (2 ^ k) +1, quindi quello che stai chiamando un numero Fermat è in realtà uno in meno.
Kelly Lowder,

@KellyLowder Sì, è davvero un Fermat 2-power.

Risposte:


8

Nim , 120 byte

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

Provalo online!

OK, questo potrebbe essere pazzo, ma qualcuno ha dovuto fare la moltiplicazione di Nim in Nim ...

Questo è un algoritmo standard di Wikipedia. Il problema è che non conosco la lingua, quindi ho dovuto imparare le basi al volo. In particolare, sono rimasto sorpreso -=e minnon ho funzionato per i set, e il modo migliore che sono riuscito a trovare per estrarre il minimo era usare l'iteratore e restituire il primo valore. Spero che gli esperti di Nim mi aiuteranno a migliorare questo.


2
Mi chiedevo quando qualcuno avrebbe provato questo.


4

Gelatina , 16 byte

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

Utilizza la formula ricorsiva xy = mex ({ay ⊕ xb ⊕ ab: a <x, b <y}) per la moltiplicazione nimber .

Provalo online!

Come funziona

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 byte

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

Non mi rendevo conto che ha questo incorporato e "procedure" anonime.

Versione originale, 36 byte:

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

O 25 byte se l'input / output potrebbe essere nimbers:

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

Beh, speravo *a**b/ a*bfunzionasse, ma non lo fa.


Sicuramente lo strumento giusto per il lavoro.

3

Pyth , 21 byte

Mf-TsmmxxgkdgkHgGdGH0

Dimostrazione

Utilizza la formulazione minima esclusa dell'elemento della moltiplicazione nim, come indicato qui .

Due mappe nidificate vengono utilizzate per scorrere su tutti i valori più piccoli ( mm ... GH), quindi i risultati vengono appiattiti ( s). Viene fornita la parte intelligente f-T ... 0, in cui si scorre ripetutamente gli interi verso l'alto da 0 per trovare il primo non contenuto nell'insieme sopra menzionato. In questo modo, non è necessario calcolare un limite superiore di iterazione, salvando alcuni byte.

Alla fine, la funzione gcalcola il prodotto nim.


3

JavaScript (ES6), 142 128 byte

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>

Il primo passo è dividere entrambi xe yin un XOR di poteri 2, prendere i loro prodotti nim a coppie e quindi XOR i risultati (perché il prodotto nim si distribuisce su XOR). Una volta che abbiamo ricorsivo al caso di xe yentrambe le potenze di 2, si nota che i poteri di Fermat si moltiplicano con l'altro usando l'aritmetica ordinaria, in modo che possiamo quindi Fattorizza xe yin poteri Fermat. Se xe ynon condividiamo un potere Fermat possiamo invertire il processo e semplicemente tornare x * y. Tuttavia, se condividono un potere Fermat, allora dividiamo entrambi xe yper quel potere, calcoliamo il prodotto nim, quindi prendiamo il prodotto nim con il quadrato nim di quel potere Fermat. 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 Language (Mathematica) , 81 byte

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

Provalo online!

Utilizzando la formula:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.