File size: 1,875 Bytes
a4da721
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
with open("input.txt") as f:
    data = f.readlines()


def check_rule(pages: list[str], rule):
    page2idx = {p: idx for idx, p in enumerate(pages)}
    r0, r1 = rule
    idx0 = page2idx.get(r0)
    idx1 = page2idx.get(r1)

    if idx0 is None or idx1 is None:
        return True # "pass"

    return idx0 < idx1


def check_rules(pages, rules):
    for rule in rules:
        passes = check_rule(pages, rule)

        if not passes:
            return False

    return True


rules = []
page_numbers = []
for line in data:
    line = line.strip("\n")
    if "|" in line:
        r1, r2 = [int(r) for r in line.split("|")]
        rules.append((r1, r2))

    elif len(line) > 0:
        page_numbers.append([int(r) for r in line.split(",")])


total = 0
for pages in page_numbers:
    passes = check_rules(pages, rules)

    if passes:
        mid_idx = len(pages) // 2
        total += pages[mid_idx]

print(total)

## Part 2

def return_failing_rule(pages, rules):
    for rule in rules:
        passes = check_rule(pages, rule)

        if not passes:
            return rule

    return None


def update_pages(pages, failed_rule):
    "Swap the pages given the failed rule"
    page2idx = {p: idx for idx, p in enumerate(pages)}
    r0, r1 = failed_rule
    idx0 = page2idx.get(r0)
    idx1 = page2idx.get(r1)
    new_pages = pages.copy()
    new_pages[idx0] = r1
    new_pages[idx1] = r0
    return new_pages


def fix_pages(pages, rules):
    failed_rule = return_failing_rule(pages, rules)
    while failed_rule:
        pages = update_pages(pages, failed_rule)
        failed_rule = return_failing_rule(pages, rules)

    return pages



total = 0
for pages in page_numbers:
    passes = check_rules(pages, rules)

    if not passes:
        new_pages = fix_pages(pages, rules)
        mid_idx = len(pages) // 2
        total += new_pages[mid_idx]

print(total)