summaryrefslogtreecommitdiff
path: root/2022/day23.py
blob: acf4d8a01a1496bff7bc0e8132f2dd66b8a0bf03 (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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python3

# import numpy as np
from functools import reduce
from re import findall
from copy import deepcopy
from collections import defaultdict
import sys

# filename = "in/day23.ref"
# filename = 'in/day23_2.ref'
filename = "in/day23.pzl"
data = open(filename).read()
lines = [line for line in data.rstrip('\n').split('\n')]
# print(lines)


E = set()
for y,line in enumerate(lines):
    for x,val in enumerate(line):
        if val == '#':
            E.add((y,x))
# print(E)

def check_N(E, y, x):
    if all( [(y+dy, x+dx) not in E for dy,dx in [[-1,0], [-1,1], [-1,-1]]] ):
        return y-1, x
    else:
        return None

def check_S(E, y, x):
    if all( [(y+dy, x+dx) not in E for dy,dx in [[1,0], [1,1], [1,-1]]] ):
        return y+1, x
    else:
        return None

def check_W(E, y, x):
    if all( [(y+dy, x+dx) not in E for dy,dx in [[0,-1], [1,-1], [-1,-1]]] ):
        return y, x-1
    else:
        return None

def check_E(E, y, x):
    if all( [(y+dy, x+dx) not in E for dy,dx in [[0,1], [1,1], [-1,1]]] ):
        return y, x+1
    else:
        return None

C = [check_N, check_S, check_W, check_E]

def get_max(E):
    min_y = 1000
    max_y = 0
    min_x = 1000
    max_x = 0
    for y,x in E:
        min_y = min(min_y, y)
        max_y = max(max_y, y)
        min_x = min(min_x, x)
        max_x = max(max_x, x)
    return min_y, max_y, min_x, max_x

def print_elfs(E):
    min_y, max_y, min_x, max_x = get_max(E)
    for y in range(min_y - 5, max_y + 5):
        for x in range(min_x - 5, max_x + 5):
            if y == 0 and x == 0:
                print('o', end='')
            elif (y,x) in E:
                print('#', end='')
            else:
                print('.', end='')
        print()
    print()
    print()


def get_new_pos(E, y, x, checks):
    checks = checks[:]

    move = False
    for dy,dx in [0,1], [0,-1], [1,0], [-1,0], [1,1], [1,-1], [-1,-1], [-1,1]:
        if (y+dy, x+dx) in E:
            move = True
            break
    if move == False:
        return y, x

    for i,check in enumerate(checks):
        ret = check(E,y,x)
        if ret != None:
            y, x = ret
            break
    return y,x


# print_elfs(E)

for round_n in range(1,10000+1):
    # print(round_n)

    Ec = E.copy()

    dest = defaultdict(list)
    for y,x in E:
        ny,nx = get_new_pos(E,y,x,C)
        dest[(ny,nx)].append((y,x))
    C.append(C.pop(0))

    for ey,ex in dest:
        if len(dest[(ey,ex)]) > 1:
            continue
        sy,sx = dest[(ey,ex)][0]
        # print(sy,sx, ey,ex)
        E.remove((sy,sx))
        E.add((ey,ex))

    # print_elfs(E)

    if round_n == 10:
        res1 = 0
        min_y, max_y, min_x, max_x = get_max(E)
        for y in range(min_y, max_y+1):
            for x in range(min_x, max_x+1):
                if (y,x) not in E:
                    res1 += 1

    if E == Ec:
        res2 = round_n
        break


print('res1:', res1)
print('res2:', res2)