summaryrefslogtreecommitdiff
path: root/17_2022.py
blob: 2ce88cf33e1e9ceb0d36de6afe73a2e0b2dcfeef (plain)
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
94
95
96
97
98
99
100
import sys

infile = sys.argv[1] if len(sys.argv) > 1 else "data/17_2022.txt"
data = open(infile).read().strip()
lines = [x for x in data.split("\n")]


def get_piece(t, y):
    if t == 0:
        return set([(2, y), (3, y), (4, y), (5, y)])
    elif t == 1:
        return set([(3, y + 2), (2, y + 1), (3, y + 1), (4, y + 1), (3, y)])
    elif t == 2:
        return set([(2, y), (3, y), (4, y), (4, y + 1), (4, y + 2)])
    elif t == 3:
        return set([(2, y), (2, y + 1), (2, y + 2), (2, y + 3)])
    elif t == 4:
        return set([(2, y + 1), (2, y), (3, y + 1), (3, y)])
    else:
        assert False


def move_left(piece):
    if any([x == 0 for (x, y) in piece]):
        return piece
    return set([(x - 1, y) for (x, y) in piece])


def move_right(piece):
    if any([x == 6 for (x, y) in piece]):
        return piece
    return set([(x + 1, y) for (x, y) in piece])


def move_down(piece):
    return set([(x, y - 1) for (x, y) in piece])


def move_up(piece):
    return set([(x, y + 1) for (x, y) in piece])


def show(r):
    max_y = max([y for (x, y) in r])
    for y in range(max_y, 0, -1):
        row = ""
        for x in range(7):
            if (x, y) in r:
                row += "#"
            else:
                row += " "
        print(row)


r = set([(x, 0) for x in range(7)])


def signature(r):
    max_y = max([y for (x, y) in r])
    return frozenset([(x, max_y - y) for (x, y) in r if max_y - y <= 30])


l = 1000000000000
seen = {}
top = 0
i = 0
t = 0
added = 0
while t < l:
    piece = get_piece(t % 5, top + 4)
    while True:
        if data[i] == "<":
            piece = move_left(piece)
            if piece & r:
                piece = move_right(piece)
        else:
            piece = move_right(piece)
            if piece & r:
                piece = move_left(piece)
        i = (i + 1) % len(data)
        piece = move_down(piece)
        if piece & r:
            piece = move_up(piece)
            r |= piece
            top = max([y for (x, y) in r])
            sr = (i, t % 5, signature(r))
            if sr in seen and t >= 2022:
                (old_t, old_y) = seen[sr]
                dy = top - old_y
                dt = t - old_t
                amt = (l - t) // dt
                added += amt * dy
                t += amt * dt
                assert t <= l
            seen[sr] = (t, top)
            break
    t += 1
    if t == 2022:
        print(top)
print(top + added)