Solution to problem 11 in Python
This commit is contained in:
parent
5e9a465064
commit
3c18e6d270
@ -168,91 +168,115 @@
|
|||||||
import re
|
import re
|
||||||
from collections import defaultdict, deque, namedtuple
|
from collections import defaultdict, deque, namedtuple
|
||||||
|
|
||||||
part1 = [1, 1, 2, 3, 2, 3, 2, 3, 2, 3]
|
# part2 = [1, 1, 2, 3, 2, 3, 2, 3, 2, 3, 1, 1, 1, 1]
|
||||||
part2 = [1, 1, 2, 3, 2, 3, 2, 3, 2, 3, 1, 1, 1, 1]
|
|
||||||
|
|
||||||
floor_re = re.compile(r"The (\w+) floor contains")
|
|
||||||
gen_re = re.compile(r"a (\w+) generator")
|
|
||||||
chip_re = re.compile(r"a (\w+)-compatible microchip")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_entry():
|
def parse_entry():
|
||||||
|
# floor_re = re.compile(r"The (\w+) floor contains")
|
||||||
|
gen_re = re.compile(r"a (\w+) generator")
|
||||||
|
chip_re = re.compile(r"a (\w+-compatible) microchip")
|
||||||
with open("files/P11.txt", "r") as f:
|
with open("files/P11.txt", "r") as f:
|
||||||
my_list = []
|
entry = defaultdict(list)
|
||||||
for idx, my_input in enumerate(f.readlines()):
|
for idx, my_input in enumerate(f.readlines(), start=1):
|
||||||
gens = gen_re.findall(my_input)
|
generators = gen_re.findall(my_input)
|
||||||
chips = chip_re.findall(my_input)
|
if generators:
|
||||||
my_list.append((idx + 1, gens, chips))
|
[entry[idx].append((idx, g)) for g in generators]
|
||||||
|
microchips = chip_re.findall(my_input)
|
||||||
|
if microchips:
|
||||||
|
[entry[idx].append((idx, m)) for m in microchips]
|
||||||
|
|
||||||
print(my_list)
|
return entry
|
||||||
|
|
||||||
|
|
||||||
# # f - floors, e - elevator, s - steps
|
def find_level_of_microchip(item, dic):
|
||||||
# State = namedtuple('State', ['f', 'e', 's'])
|
for key in dic.keys():
|
||||||
|
for val in dic[key]:
|
||||||
# def valid(state):
|
if f"{item}-compatible" in val:
|
||||||
# if not 1 <= state.e <= 4:
|
return val[0]
|
||||||
# return False
|
|
||||||
|
|
||||||
# for idx, val in enumerate(state.f[1::2]):
|
|
||||||
# idx = idx * 2 + 1
|
|
||||||
# if val != state.f[idx - 1] and any(val == i for i in state.f[0::2]):
|
|
||||||
# return False
|
|
||||||
# return True
|
|
||||||
|
|
||||||
# def solved(state):
|
|
||||||
# return all(i == 4 for i in state.f)
|
|
||||||
|
|
||||||
|
|
||||||
# def generalize(state):
|
def get_floor_config(dic):
|
||||||
# generators = [sum(1 for v in state.f[::2] if v == floor) for floor in range(1, 5)]
|
floor_config = []
|
||||||
# microchips = [sum(1 for v in state.f[1::2] if v == floor) for floor in range(1, 5)]
|
for lvl in dic.keys():
|
||||||
|
for items in dic[lvl]:
|
||||||
|
if "-compatible" not in items[1]:
|
||||||
|
floor_config.append(items[0])
|
||||||
|
lvl_comp = find_level_of_microchip(items[1], dic)
|
||||||
|
floor_config.append(lvl_comp)
|
||||||
|
|
||||||
# return ''.join(map(str, generators + microchips)) + str(state.e)
|
return floor_config
|
||||||
|
|
||||||
|
|
||||||
# def bfs(floor_config):
|
# f - floors, e - elevator, s - steps
|
||||||
# bfs_q = deque()
|
State = namedtuple("State", ["f", "e", "s"])
|
||||||
# bfs_q.append(State(floor_config, 1, 0))
|
|
||||||
# seen = set()
|
|
||||||
# while bfs_q:
|
|
||||||
# state = bfs_q.popleft()
|
|
||||||
# if solved(state):
|
|
||||||
# print(f"We need {state.s} steps")
|
|
||||||
# return
|
|
||||||
# if generalize(state) in seen or not valid(state):
|
|
||||||
# continue
|
|
||||||
# seen.add(generalize(state))
|
|
||||||
|
|
||||||
|
|
||||||
# for idx in range(len(state.f)):
|
def valid(state):
|
||||||
# i = state.f[idx]
|
if not 1 <= state.e <= 4:
|
||||||
# if i != state.e: # item can't be moved bc not in elevator
|
return False
|
||||||
# continue
|
|
||||||
# state.f[idx] -= 1
|
|
||||||
# bfs_q.append(State(list(state.f), state.e - 1, state.s + 1))
|
|
||||||
# state.f[idx] += 2
|
|
||||||
# bfs_q.append(State(list(state.f), state.e + 1, state.s + 1))
|
|
||||||
# state.f[idx] -= 1
|
|
||||||
|
|
||||||
# for jdx in range(idx + 1, len(state.f)):
|
for idx, val in enumerate(state.f[1::2]):
|
||||||
# if state.f[jdx] != state.e:
|
idx = idx * 2 + 1
|
||||||
# continue
|
if val != state.f[idx - 1] and any(val == i for i in state.f[0::2]):
|
||||||
# state.f[jdx] -= 1
|
return False
|
||||||
# state.f[idx] -= 1
|
return True
|
||||||
# bfs_q.append(State(list(state.f), state.e - 1,
|
|
||||||
# state.s + 1))
|
|
||||||
# state.f[jdx] += 2
|
|
||||||
# state.f[idx] += 2
|
|
||||||
# bfs_q.append(State(list(state.f), state.e + 1,
|
|
||||||
# state.s + 1))
|
|
||||||
# state.f[jdx] -= 1
|
|
||||||
# state.f[idx] -= 1
|
|
||||||
|
|
||||||
|
|
||||||
# def part_1():
|
def solved(state):
|
||||||
# p1 = parse_entry()
|
return all(i == 4 for i in state.f)
|
||||||
# bfs(p1)
|
|
||||||
|
|
||||||
|
def generalize(state):
|
||||||
|
generators = [
|
||||||
|
sum(1 for v in state.f[::2] if v == floor) for floor in range(1, 5)
|
||||||
|
]
|
||||||
|
microchips = [
|
||||||
|
sum(1 for v in state.f[1::2] if v == floor) for floor in range(1, 5)
|
||||||
|
]
|
||||||
|
|
||||||
|
return "".join(map(str, generators + microchips)) + str(state.e)
|
||||||
|
|
||||||
|
|
||||||
|
def bfs(floor_config):
|
||||||
|
bfs_q = deque()
|
||||||
|
bfs_q.append(State(floor_config, 1, 0))
|
||||||
|
seen = set()
|
||||||
|
while bfs_q:
|
||||||
|
state = bfs_q.popleft()
|
||||||
|
if solved(state):
|
||||||
|
# print(f"We need {state.s} steps")
|
||||||
|
return state.s
|
||||||
|
if generalize(state) in seen or not valid(state):
|
||||||
|
continue
|
||||||
|
seen.add(generalize(state))
|
||||||
|
|
||||||
|
for idx in range(len(state.f)):
|
||||||
|
i = state.f[idx]
|
||||||
|
if i != state.e: # item can't be moved bc not in elevator
|
||||||
|
continue
|
||||||
|
state.f[idx] -= 1
|
||||||
|
bfs_q.append(State(list(state.f), state.e - 1, state.s + 1))
|
||||||
|
state.f[idx] += 2
|
||||||
|
bfs_q.append(State(list(state.f), state.e + 1, state.s + 1))
|
||||||
|
state.f[idx] -= 1
|
||||||
|
|
||||||
|
for jdx in range(idx + 1, len(state.f)):
|
||||||
|
if state.f[jdx] != state.e:
|
||||||
|
continue
|
||||||
|
state.f[jdx] -= 1
|
||||||
|
state.f[idx] -= 1
|
||||||
|
bfs_q.append(State(list(state.f), state.e - 1, state.s + 1))
|
||||||
|
state.f[jdx] += 2
|
||||||
|
state.f[idx] += 2
|
||||||
|
bfs_q.append(State(list(state.f), state.e + 1, state.s + 1))
|
||||||
|
state.f[jdx] -= 1
|
||||||
|
state.f[idx] -= 1
|
||||||
|
|
||||||
|
|
||||||
|
def part_1():
|
||||||
|
p1 = get_floor_config(parse_entry())
|
||||||
|
print(f"We need {bfs(p1)} steps for part 1")
|
||||||
|
|
||||||
|
|
||||||
# # --- Part Two ---
|
# # --- Part Two ---
|
||||||
|
|
||||||
@ -274,7 +298,13 @@ def parse_entry():
|
|||||||
# # including these four new ones, to the fourth floor?
|
# # including these four new ones, to the fourth floor?
|
||||||
|
|
||||||
|
|
||||||
# if __name__ == '__main__':
|
def part_2():
|
||||||
# parse_entry()
|
p2 = get_floor_config(parse_entry())
|
||||||
# # bfs(part1)
|
# extra parts are on floor 1
|
||||||
# # bfs(part2)
|
p2.extend([1, 1, 1, 1])
|
||||||
|
print(f"We need {bfs(p2)} steps for part 2")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
part_1()
|
||||||
|
part_2()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user