adventofcode2024/day05/sol.py

107 lines
2.5 KiB
Python

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
t = 0
invalid = []
for pages in updates:
if isvalid(pages):
print(pages)
t += int(pages[len(pages)//2])
else:
invalid.append(pages)
print(t)
t = 0
for pages in invalid:
rules2 = [(p,g) for p,g in rules if p in pages and g in pages]
#print(pages, rules2)
S = set(p for p,g in rules2)
E = set(g for p,g in rules2)
top = next(iter(S-E))
# 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()
print(l)
t += int(l[len(l)//2])
print(t)
# failed attempt: establish a total order by iterating the graph
# to a fix point and then using it to sort the list.
# failed because the graph is cyclic
"""
less = {p:set() for p,g in rules}
for p,g in rules:
less[p].add(g)
print("less")
for p in less:
print(p,less[p])
done = False
while not done:
done = True
for p in less:
for g in list(less[p]):
if g in less:
e = less[g] - less[p]
if e:
less[p] |= e
done = False
print("less2")
for p in less:
print(p,less[p])
def compare(a,b):
if a == b:
return 0
if a in less and b in less[a]:
return -1
return 1
t = 0
for pages in invalid:
pages.sort(key = functools.cmp_to_key(compare))
print(pages)
assert(isvalid(pages))
t += int(pages[len(pages)//2])
print(t)
"""
solve(open("sample1.in"))
solve(open("input"))