105 lines
2.9 KiB
Python
105 lines
2.9 KiB
Python
|
"""
|
||
|
Animation of solving an AdventOfCode Challenge
|
||
|
"""
|
||
|
# requires: python-fluepdot, python-dotenv
|
||
|
|
||
|
import os
|
||
|
from time import perf_counter, sleep
|
||
|
from typing import Callable
|
||
|
from dotenv import load_dotenv
|
||
|
from fluepdot import Fluepdot, Mode
|
||
|
|
||
|
load_dotenv()
|
||
|
|
||
|
fd = Fluepdot(os.getenv('DOTS_HOST'))
|
||
|
fd.set_mode(Mode.DIFFERENTIAL)
|
||
|
|
||
|
DELAY = .001
|
||
|
|
||
|
def clear():
|
||
|
x, y = fd.get_size()
|
||
|
arr = [[False for _ in range(x)] for _ in range(y)]
|
||
|
fd.post_frame(arr)
|
||
|
|
||
|
def profiler(method):
|
||
|
def profiler_method(*arg, **kw):
|
||
|
t = perf_counter()
|
||
|
ret = method(*arg, **kw)
|
||
|
print(f'{method.__name__} method took : {perf_counter()-t:.4f} sec')
|
||
|
return ret
|
||
|
return profiler_method
|
||
|
|
||
|
def transpose(m):
|
||
|
return [''.join([m[j][i] for j in range(len(m))]) for i in range(len(m[0]))]
|
||
|
|
||
|
def get_reflection(mirror: list[str]) -> int | Exception:
|
||
|
fdx, fdy = fd.get_size()
|
||
|
for x in range(1, len(mirror)):
|
||
|
sol = True
|
||
|
draw_arr = [[False for _ in range(fdx)] for _ in range(fdy)]
|
||
|
offset = 0
|
||
|
for ind, (c1, c2) in enumerate(zip(mirror[x:], mirror[x-1::-1])):
|
||
|
for i, c in enumerate(c1):
|
||
|
if c == '#':
|
||
|
draw_arr[ind+offset][i] = True
|
||
|
for i, c in enumerate(c2):
|
||
|
if c == '#':
|
||
|
draw_arr[ind+offset][i+len(c1)+5] = True
|
||
|
if c1 == c2:
|
||
|
draw_arr[ind+offset][len(c1)+5+len(c2)+5] = True
|
||
|
else:
|
||
|
sol = False
|
||
|
if ind+offset == fdy:
|
||
|
fd.post_frame(draw_arr)
|
||
|
sleep(DELAY)
|
||
|
offset -= fdy
|
||
|
else:
|
||
|
fd.post_frame(draw_arr)
|
||
|
sleep(DELAY)
|
||
|
if sol:
|
||
|
fd.post_text(f'Mirror at {x}')
|
||
|
return x
|
||
|
return Exception('No reflection found')
|
||
|
|
||
|
def get_reflection2(mirror: list[str]) -> int | Exception:
|
||
|
for x in range(len(mirror)):
|
||
|
errors = 0
|
||
|
errors += sum(s1!=s2 for c1, c2 in zip(mirror[x:], mirror[x-1::-1]) for s1, s2 in zip(c1, c2))
|
||
|
if errors == 1:
|
||
|
return x
|
||
|
return Exception('No reflection found')
|
||
|
|
||
|
def get_reflection_line(func: Callable[[list[str]], int], mirror: list[str]) -> int:
|
||
|
# check for vertical reflection across a horizontal line
|
||
|
ind = func(mirror)
|
||
|
if isinstance(ind, int):
|
||
|
return 100*ind
|
||
|
# check for horizontal reflection across a vertical line
|
||
|
ind = func(transpose(mirror))
|
||
|
if isinstance(ind, int):
|
||
|
return ind
|
||
|
raise ind
|
||
|
|
||
|
# Part 1:
|
||
|
def part1(mirrors: list[list[str]]) -> int:
|
||
|
return sum([get_reflection_line(get_reflection, mirror) for mirror in mirrors])
|
||
|
|
||
|
# Part 2:
|
||
|
def part2(mirrors: list[list[str]]) -> int:
|
||
|
return sum([get_reflection_line(get_reflection2, mirror) for mirror in mirrors])
|
||
|
|
||
|
def get_input():
|
||
|
with open(os.path.dirname(os.path.realpath(__file__))+'/assets/input', 'r', encoding='utf-8') as f:
|
||
|
content = [s.strip().split('\n') for s in f.read().rstrip().split('\n\n')]
|
||
|
return content
|
||
|
|
||
|
@profiler
|
||
|
def solve():
|
||
|
mirrors = get_input()
|
||
|
fd.post_text(f'Part 1: {part1(mirrors)}')
|
||
|
sleep(10)
|
||
|
fd.post_text(f'Part 2: {part2(mirrors)}')
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
solve()
|