diff --git a/python/e301.py b/python/e301.py new file mode 100644 index 0000000..20e4ec2 --- /dev/null +++ b/python/e301.py @@ -0,0 +1,70 @@ +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) +