···33from itertools import combinations
445566-def complete(state):
77- return all(f == 3 for f in state)
88-99-106def valid(state):
77+ """Returns whether the current state is valid or not."""
118 gens = set(state[::2])
129 for i, floor in enumerate(state):
1310 # Element is a chip if it has an odd index
1411 if i % 2 == 1:
1515- # Its matching generator is on the same floor, so it's fine
1616- if state[i-1] == floor:
1212+ # Chip's matching generator is on the same floor
1313+ if state[i - 1] == floor:
1714 continue
18151916 # There is another generator on the floor
···242125222623def ordered(state):
2727- substate = sorted(zip(state[::2], state[1::2]))
2828- return tuple(item for subl in substate for item in subl)
2424+ """Returns an ordered version of the state (to improve node pruning)."""
2525+ sorted_state = sorted(zip(state[::2], state[1::2]))
2626+ return tuple(item for subl in sorted_state for item in subl)
292730283129def solve(state, start_floor=0):
3232- if start_floor == 3 and complete(state):
3333- return 0
3434-3530 horizon = [(start_floor, state)]
3631 steps = 0
3732 seen = set()
···4338 can_move = [i for i, f in enumerate(state) if f == floor]
4439 moves = []
45404646- if floor < 3:
4141+ if floor < TOP_FLOOR:
4742 moves.extend([(2, floor + 1), (1, floor + 1)])
48434944 if floor > 0:
···6560 for move in combinations(can_move, n):
6661 next_state = tuple(new_floor if i in move else f for i, f in enumerate(state))
67626868- if complete(next_state):
6363+ # All items are on the top floor, so we're done
6464+ if all(f == TOP_FLOOR for f in next_state):
6965 return steps + 1
70667167 if valid(next_state) and (new_floor, ordered(next_state)) not in seen:
···8177 steps += 1
827883798080+TOP_FLOOR = None
8481generators = {}
8582microchips = {}
8683···9087 for chip in re.findall(r'(\w+)-compatible microchip', line):
9188 microchips[chip] = i
92899090+ TOP_FLOOR = i
9191+93929493STATE = []
9594···102101print "Minimum number of steps:", solve(STATE)
103102104103STATE = tuple(list(STATE) + [0, 0, 0, 0])
105105-print "With four new objects:", solve(STATE)
104104+print "Including 4 new objects:", solve(STATE)