#!/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)