Nimber arithmetic: Difference between revisions

Added C++ solution
(promoting to task- seems stable enough now)
(Added C++ solution)
Line 86:
printf("\n%d + %d = %d\n", a, b, nimsum(a, b));
printf("%d * %d = %d\n", a, b, nimprod(a, b));
return 0;
}</lang>
 
{{out}}
<pre>
+ | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
--- -------------------------------------------------
0 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 | 1 0 3 2 5 4 7 6 9 8 11 10 13 12 15 14
2 | 2 3 0 1 6 7 4 5 10 11 8 9 14 15 12 13
3 | 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12
4 | 4 5 6 7 0 1 2 3 12 13 14 15 8 9 10 11
5 | 5 4 7 6 1 0 3 2 13 12 15 14 9 8 11 10
6 | 6 7 4 5 2 3 0 1 14 15 12 13 10 11 8 9
7 | 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8
8 | 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7
9 | 9 8 11 10 13 12 15 14 1 0 3 2 5 4 7 6
10 | 10 11 8 9 14 15 12 13 2 3 0 1 6 7 4 5
11 | 11 10 9 8 15 14 13 12 3 2 1 0 7 6 5 4
12 | 12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3
13 | 13 12 15 14 9 8 11 10 5 4 7 6 1 0 3 2
14 | 14 15 12 13 10 11 8 9 6 7 4 5 2 3 0 1
15 | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
 
* | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
--- -------------------------------------------------
0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2 | 0 2 3 1 8 10 11 9 12 14 15 13 4 6 7 5
3 | 0 3 1 2 12 15 13 14 4 7 5 6 8 11 9 10
4 | 0 4 8 12 6 2 14 10 11 15 3 7 13 9 5 1
5 | 0 5 10 15 2 7 8 13 3 6 9 12 1 4 11 14
6 | 0 6 11 13 14 8 5 3 7 1 12 10 9 15 2 4
7 | 0 7 9 14 10 13 3 4 15 8 6 1 5 2 12 11
8 | 0 8 12 4 11 3 7 15 13 5 1 9 6 14 10 2
9 | 0 9 14 7 15 6 1 8 5 12 11 2 10 3 4 13
10 | 0 10 15 5 3 9 12 6 1 11 14 4 2 8 13 7
11 | 0 11 13 6 7 12 10 1 9 2 4 15 14 5 3 8
12 | 0 12 4 8 13 1 9 5 6 10 2 14 11 7 15 3
13 | 0 13 6 11 9 4 15 2 14 3 8 5 7 10 1 12
14 | 0 14 7 9 5 11 2 12 10 4 13 3 15 1 8 6
15 | 0 15 5 10 1 14 4 11 2 13 7 8 3 12 6 9
 
21508 + 42689 = 62149
21508 * 42689 = 35202
</pre>
 
=={{header|C++}}==
{{trans|FreeBASIC}}
<lang cpp>#include <cstdint>
#include <functional>
#include <iomanip>
#include <iostream>
 
// highest power of 2 that divides a given number
uint32_t hpo2(uint32_t n) {
return n & -n;
}
 
// base 2 logarithm of the highest power of 2 dividing a given number
uint32_t lhpo2(uint32_t n) {
uint32_t q = 0, m = hpo2(n);
for (; m % 2 == 0; m >>= 1, ++q) {}
return q;
}
 
// nim-sum of two numbers
uint32_t nimsum(uint32_t x, uint32_t y) {
return x ^ y;
}
 
// nim-product of two numbers
uint32_t nimprod(uint32_t x, uint32_t y) {
if (x < 2 || y < 2)
return x * y;
uint32_t h = hpo2(x);
if (x > h)
return nimprod(h, y) ^ nimprod(x ^ h, y);
if (hpo2(y) < y)
return nimprod(y, x);
uint32_t xp = lhpo2(x), yp = lhpo2(y);
uint32_t comp = xp & yp;
if (comp == 0)
return x * y;
h = hpo2(comp);
return nimprod(nimprod(x >> h, y >> h), 3 << (h - 1));
}
 
void print_table(uint32_t n, char op, std::function<uint32_t(uint32_t, uint32_t)> func) {
std::cout << ' ' << op << " |";
for (uint32_t a = 0; a <= n; ++a)
std::cout << std::setw(3) << a;
std::cout << "\n--- -";
for (uint32_t a = 0; a <= n; ++a)
std::cout << "---";
std::cout << '\n';
for (uint32_t b = 0; b <= n; ++b) {
std::cout << std::setw(2) << b << " |";
for (uint32_t a = 0; a <= n; ++a)
std::cout << std::setw(3) << func(a, b);
std::cout << '\n';
}
}
 
int main() {
print_table(15, '+', nimsum);
printf("\n");
print_table(15, '*', nimprod);
const uint32_t a = 21508, b = 42689;
std::cout << '\n';
std::cout << a << " + " << b << " = " << nimsum(a, b) << '\n';
std::cout << a << " * " << b << " = " << nimprod(a, b) << '\n';
return 0;
}</lang>
1,777

edits