Skip to content

Commit 0f2d57c

Browse files
committed
2024: Day 5
1 parent c12acc0 commit 0f2d57c

File tree

5 files changed

+1440
-1
lines changed

5 files changed

+1440
-1
lines changed

2024/python/day4/__main__.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import re
21
from itertools import product
32

43
from utils.file import read_input

2024/python/day5/__init__.py

Whitespace-only changes.

2024/python/day5/__main__.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from collections.abc import Iterable
2+
from math import floor
3+
4+
from black.trans import defaultdict
5+
from more_itertools.recipes import partition
6+
7+
from utils.file import read_input
8+
9+
lines = read_input(__package__)
10+
11+
rules: list[tuple[int, int]] = []
12+
updates: list[list[int]] = []
13+
for line in lines:
14+
if line[2] == "|":
15+
rules.append((int(line[:2]), int(line[3:])))
16+
elif "," in line:
17+
updates.append(list(map(int, line.split(","))))
18+
19+
rules_after = defaultdict(set)
20+
rules_before = defaultdict(set)
21+
for rule in rules:
22+
rules_after[rule[0]].add(rule[1])
23+
rules_before[rule[1]].add(rule[0])
24+
25+
26+
def check_rule(page: int, before: list[int], after: list[int]) -> bool:
27+
return all(p not in rules_after[page] for p in before) and all(p not in rules_before[page] for p in after)
28+
29+
30+
def is_ordered(pages: list[int]) -> bool:
31+
return all(check_rule(pages[i], pages[:i], pages[i + 1 :]) for i in range(len(pages)))
32+
33+
34+
def middle_pages(updates_: Iterable[list[int]]) -> Iterable[int]:
35+
return (update[floor((len(update) - 1) / 2)] for update in updates_)
36+
37+
38+
unordered, ordered = partition(is_ordered, updates)
39+
print("Part 1", sum(middle_pages(ordered)))
40+
41+
42+
def reorder(pages_: list[int]):
43+
pages = pages_[:] # Copy before mutations
44+
while not is_ordered(pages): # Pray for no infinite loop
45+
for i in range(len(pages)):
46+
page = pages[i]
47+
before, after = pages[:i], pages[i + 1 :]
48+
rule_before, rule_after = rules_before[page], rules_after[page]
49+
50+
move_before = next((p for p in before if p in rule_after), None)
51+
if move_before:
52+
pages = pages[:i] + pages[i + 1 :]
53+
idx = pages.index(move_before)
54+
pages.insert(idx, page)
55+
break
56+
move_after = next((p for p in after if p in rule_before), None)
57+
if move_after:
58+
pages = pages[:i] + pages[i + 1 :]
59+
idx = -pages[::-1].index(move_after)
60+
if idx == 0:
61+
pages.append(page)
62+
else:
63+
pages.insert(idx, page)
64+
return pages
65+
66+
67+
reordered = list(map(reorder, unordered))
68+
print("Part 2", sum(middle_pages(reordered)))

0 commit comments

Comments
 (0)