fluepdot-scripts/aoc13.py

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