-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathday_11.py
79 lines (61 loc) · 2.61 KB
/
day_11.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
74
75
76
77
78
79
from collections import deque
def make_hash(gens, chips, lift, *args):
g = [gens.count(str(i)) for i in range(4)]
c = [chips.count(str(i)) for i in range(4)]
return ''.join(map(str, g+c)) + str(lift)
def is_invalid(gens, chips, lift, *args):
if lift not in range(4):
return True
for generator, chip in zip(gens, chips):
if chip != generator and any(gen == chip for gen in gens):
return True
return False
def is_solved(positions):
return all(pos == 3 for pos in positions)
def get_gcls(positions, l, s):
g = ''.join(map(str, positions[: len(positions)//2]))
c = ''.join(map(str, positions[len(positions)//2 :]))
return g, c, l, s
def calculate_steps(gens, chips, lift, steps):
seen = set()
que = deque([(gens, chips, lift, steps)])
while que:
*state, steps = que.popleft()
hash_ = make_hash(*state)
if hash_ in seen or is_invalid(*state):
continue
seen.add(hash_)
positions = list(map(int, ''.join(state[:-1])))
lift = state[-1]
if is_solved(positions):
return steps
for i, first in enumerate(positions):
if first == lift:
if lift < 3:
positions[i] += 1
que.append(get_gcls(positions, lift+1, steps+1))
positions[i] -= 1
if lift > 0:
positions[i] -= 1
que.append(get_gcls(positions, lift-1, steps+1))
positions[i] += 1
for j, second in enumerate(positions[i+1:], i+1):
if second == lift:
if lift < 3:
positions[i] += 1
positions[j] += 1
que.append(get_gcls(positions, lift+1, steps+1))
positions[i] -= 1
positions[j] -= 1
if lift > 0:
positions[i] -= 1
positions[j] -= 1
que.append(get_gcls(positions, lift-1, steps+1))
positions[i] += 1
positions[j] += 1
first_solution = calculate_steps(gens='01111', chips='02222', lift=0, steps=0)
second_solution = calculate_steps(gens='0001111', chips='0002222', lift=0, steps=0)
print("I should bring all those things to 4th floor!")
print(f"By my calculation, it should take no more than {first_solution} steps.")
print('....')
print(f"Even if there were two more elements, it should be {second_solution} steps total.")