euler/python/e301.py

71 lines
1.6 KiB
Python
Raw Normal View History

2024-04-19 14:00:53 +02:00
from functools import lru_cache
@lru_cache
def x_naiv(s):
zcount = s.count(0)
if zcount == 3:
return 0
elif zcount == 2:
return 1
elif zcount == 1:
sl = list(s)
sl.remove(0)
if sl[0] == sl[1]:
return 0
s = list(s)
for i in range(len(s)):
for v in range(1, s[i] + 1):
ns = list(s)
ns[i] -= v
if x_naiv(tuple(sorted(ns))) == 0:
# Other player loses.
return 1
return 0
def x_nim_sum(s):
""" I wasn't able to deduce this myself quickly and looked it up instead. """
return 0 if (s[0] ^ s[1] ^ s[2]) == 0 else 1
def test_nim_functions():
assert(x_naiv(tuple([0, 0, 0])) == 0)
assert(x_naiv(tuple([1, 0, 0])) == 1)
assert(x_naiv(tuple([1, 1, 0])) == 0)
assert(x_naiv(tuple([1, 1, 1])) == 1)
assert(x_naiv(tuple([1, 2, 3])) == 0)
for n1 in range(0, 8):
for n2 in range(1, n1 + 1):
for n3 in range(1, n2 + 1):
s = tuple([n1, n2, n3])
assert x_naiv(s) == x_nim_sum(s)
def euler_301():
test_nim_functions()
# log(2**30, 10) ~= 9 -> 1 billion easy brute force
# Probably a more efficient computation is possible by counting the permutations
# where all binary digits are zero.
# 0 0 0 -> 0
# 0 0 1 -> 0
# 0 1 1 -> 0
r = 0
for n in range(1, 2**30 + 1):
s = tuple([n, 2 * n, 3 * n])
xr = x_nim_sum(s)
if xr == 0:
r += 1
return r
if __name__ == "__main__":
solution = euler_301()
print("e301.py: " + str(solution))
# assert(solution == 0)