-
Notifications
You must be signed in to change notification settings - Fork 0
/
169.py
73 lines (63 loc) · 1.78 KB
/
169.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
from math import log
def decompose(n, base=2):
if n == 0: return [0]
result = []
k = int(log(n)/log(base))
remain = n
while k >= 0:
d = remain/base**k
result.append(d)
remain -= d*base**k
k -= 1
return result
memo = {}
def solve(l):
if len(l) == 0: return 1
if len(l) == 1: return l[0] <= 2
if memo.has_key(l): return memo[l]
# find the next non zero power of two
if 1 in l[1:]: k = l[1:].index(1)
else: k = len(l) - 1
if l[0] == 1:
result = (k+1)*solve(l[k+1:]) + solve((3,) + l[k+2:])
else: # here l[0] == 3
if l[0] != 3: raise("problem")
result = k*solve(l[k+1:]) + solve((3,) + l[k+2:])
memo[l] = result
return result
def problem169(N=10**25):
d = tuple(decompose(N))
return solve(d)
print problem169()
"""
the following functions were used to compute a first algorithm:
very slow but useful to check the correctness of other
algorithms for small values
"""
def is_valid(l):
return reduce(lambda x,y: x and y, [i <= 2 for i in l])
def find_next(l):
result = []
for i in range(1, len(l)):
if l[i] > 3: return []
if l[i] > 0 and (l[i-1] == 0 or (i > 1 and l[i-1] == 1 and l[i-2] <= 1)):
temp = [el for el in l]
temp[i] -= 1
temp[i-1] += 2
if temp[0] <= 2:
result.append(temp)
return result
def problem169_too_slow(n=10):
d = decompose(n)
d.reverse()
frontier, seen = [d], []
result = 0
while frontier:
current = frontier.pop()
if is_valid(current):
result += 1
for next in find_next(current):
if not next in seen:
frontier.append(next)
seen.append(current)
return result