summaryrefslogtreecommitdiff
path: root/2022/day23.py
blob: 27287ba134c7267691f7fa1723f965439444dabe (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/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)

res1 = 0
res2 = 0


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

E = set()
N = list()
for y,line in enumerate(lines):
    for x,val in enumerate(line):
        if val == '#':
            E.add((y,x))
            N.append( (y,x, [check_N, check_S, check_W, check_E]) )
# print(E)
# print(N)

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:
        checks.append(checks.pop(0))
        return y, x, checks

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

    # print('changing order', y, x, i, checks)
    # checks.append(checks.pop(i))
    checks.append(checks.pop(0))
    return y,x, checks



print_elfs(E)


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

    Ec = E.copy()

    dest = defaultdict(list)
    for y,x in E:

        for i, (yy,xx,_) in enumerate(N):
            if yy == y and xx == x:
                break
        else:
            assert False

        checks = N[i][2]
        ny,nx,checks = get_new_pos(E,y,x,checks)

        dest[(ny,nx)].append((y,x))
        N[i] = (y,x, checks)


    # print(dest)

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

        for i, (yy,xx,checks) in enumerate(N):
            if yy == sy and xx == sx:
                break
        else:
            assert False
        N[i] = (ey,ex,checks)

    # print(E)
    # print(N)
    print_elfs(E)
    if E == Ec:
        break


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

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