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"))