adventofcode2024/day05/sol.py

78 lines
1.8 KiB
Python
Raw Permalink Normal View History

2024-12-05 07:52:55 +00:00
import functools
def parse(file):
rules = []
for line in file:
line = line.strip()
if line == "":
break
a, _, b = line.partition('|')
rules.append((a,b))
updates = []
for line in file:
line = line.strip()
updates.append(line.split(','))
return rules, updates
def solve(file):
rules, updates = parse(file)
rules = set(rules)
def isvalid(pages):
for i in range(len(pages)):
p = pages[i]
for g in pages[i+1:]:
if (g,p) in rules:
return False
return True
2024-12-05 08:11:04 +00:00
# part 1
2024-12-05 07:52:55 +00:00
t = 0
invalid = []
for pages in updates:
if isvalid(pages):
print(pages)
t += int(pages[len(pages)//2])
else:
invalid.append(pages)
print(t)
2024-12-05 08:11:04 +00:00
# part 2: select applicable rules and form a graph
# find the root node
# do a topological sort by doing a DFS of the graph
2024-12-05 08:07:02 +00:00
t = 0
for pages in invalid:
2024-12-05 08:11:04 +00:00
# select rules
2024-12-05 08:07:02 +00:00
rules2 = [(p,g) for p,g in rules if p in pages and g in pages]
#print(pages, rules2)
2024-12-05 08:11:04 +00:00
# find root node
2024-12-05 08:07:02 +00:00
S = set(p for p,g in rules2)
E = set(g for p,g in rules2)
top = next(iter(S-E))
2024-12-05 08:11:04 +00:00
2024-12-05 08:07:02 +00:00
# topological sort
l = []
seen = set()
def visit(node):
if node in seen: return
seen.add(node)
for p,g in rules2:
if p == node and g not in seen:
visit(g)
l.append(node)
visit(top)
l.reverse()
2024-12-05 08:11:04 +00:00
# sanity check
assert len(l) == len(pages)
assert isvalid(l)
2024-12-05 08:07:02 +00:00
print(l)
2024-12-05 08:11:04 +00:00
# add middle number to total
2024-12-05 08:07:02 +00:00
t += int(l[len(l)//2])
print(t)
2024-12-05 07:52:55 +00:00
solve(open("sample1.in"))
solve(open("input"))