diff --git a/advent/days/day10/__init__.py b/advent/days/day10/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/advent/days/day10/data/expected.txt b/advent/days/day10/data/expected.txt new file mode 100644 index 0000000..ecee815 --- /dev/null +++ b/advent/days/day10/data/expected.txt @@ -0,0 +1,6 @@ +## ## ## ## ## ## ## ## ## ## +### ### ### ### ### ### ### +#### #### #### #### #### +##### ##### ##### ##### +###### ###### ###### #### +####### ####### ####### \ No newline at end of file diff --git a/advent/days/day10/data/input.txt b/advent/days/day10/data/input.txt new file mode 100644 index 0000000..1dd9a1d --- /dev/null +++ b/advent/days/day10/data/input.txt @@ -0,0 +1,143 @@ +noop +addx 26 +addx -21 +addx 2 +addx 3 +noop +noop +addx 23 +addx -17 +addx -1 +noop +noop +addx 7 +noop +addx 3 +addx 1 +noop +noop +addx 2 +noop +addx 7 +noop +addx -12 +addx 13 +addx -38 +addx 5 +addx 34 +addx -2 +addx -29 +addx 2 +addx 5 +addx 2 +addx 3 +addx -2 +addx -1 +addx 8 +addx 2 +addx 6 +addx -26 +addx 23 +addx -26 +addx 33 +addx 2 +addx -37 +addx -1 +addx 1 +noop +noop +noop +addx 5 +addx 5 +addx 3 +addx -2 +addx 2 +addx 5 +addx 5 +noop +noop +addx -2 +addx 4 +noop +noop +noop +addx 3 +noop +noop +addx 7 +addx -1 +addx -35 +addx -1 +addx 5 +addx 3 +noop +addx 4 +noop +noop +noop +noop +noop +addx 5 +addx 1 +noop +noop +noop +addx -7 +addx 12 +addx 2 +addx 7 +noop +addx -2 +noop +noop +addx 7 +addx 2 +addx -39 +noop +noop +addx 5 +addx 2 +addx -4 +addx 25 +addx -18 +addx 7 +noop +addx -2 +addx 5 +addx 2 +addx 6 +addx -5 +addx 2 +addx -22 +addx 29 +addx -21 +addx -7 +addx 31 +addx 2 +noop +addx -36 +addx 1 +addx 5 +noop +addx 1 +addx 4 +addx 5 +noop +noop +noop +addx 3 +noop +addx -13 +addx 15 +noop +addx 5 +noop +addx 1 +noop +addx 3 +addx 2 +addx 4 +addx 3 +noop +addx -3 +noop diff --git a/advent/days/day10/data/test01.txt b/advent/days/day10/data/test01.txt new file mode 100644 index 0000000..94cd0a8 --- /dev/null +++ b/advent/days/day10/data/test01.txt @@ -0,0 +1,146 @@ +addx 15 +addx -11 +addx 6 +addx -3 +addx 5 +addx -1 +addx -8 +addx 13 +addx 4 +noop +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx -35 +addx 1 +addx 24 +addx -19 +addx 1 +addx 16 +addx -11 +noop +noop +addx 21 +addx -15 +noop +noop +addx -3 +addx 9 +addx 1 +addx -3 +addx 8 +addx 1 +addx 5 +noop +noop +noop +noop +noop +addx -36 +noop +addx 1 +addx 7 +noop +noop +noop +addx 2 +addx 6 +noop +noop +noop +noop +noop +addx 1 +noop +noop +addx 7 +addx 1 +noop +addx -13 +addx 13 +addx 7 +noop +addx 1 +addx -33 +noop +noop +noop +addx 2 +noop +noop +noop +addx 8 +noop +addx -1 +addx 2 +addx 1 +noop +addx 17 +addx -9 +addx 1 +addx 1 +addx -3 +addx 11 +noop +noop +addx 1 +noop +addx 1 +noop +noop +addx -13 +addx -19 +addx 1 +addx 3 +addx 26 +addx -30 +addx 12 +addx -1 +addx 3 +addx 1 +noop +noop +noop +addx -9 +addx 18 +addx 1 +addx 2 +noop +noop +addx 9 +noop +noop +noop +addx -1 +addx 2 +addx -37 +addx 1 +addx 3 +noop +addx 15 +addx -21 +addx 22 +addx -6 +addx 1 +noop +addx 2 +addx 1 +noop +addx -10 +noop +noop +addx 20 +addx 1 +addx 2 +addx 2 +addx -6 +addx -11 +noop +noop +noop \ No newline at end of file diff --git a/advent/days/day10/data/test02.txt b/advent/days/day10/data/test02.txt new file mode 100644 index 0000000..fd7eba8 --- /dev/null +++ b/advent/days/day10/data/test02.txt @@ -0,0 +1,3 @@ +noop +addx 3 +addx -5 \ No newline at end of file diff --git a/advent/days/day10/solution.py b/advent/days/day10/solution.py new file mode 100644 index 0000000..70884a7 --- /dev/null +++ b/advent/days/day10/solution.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from typing import Iterator + +day_num = 10 + + +def part1(lines: Iterator[str]) -> int: + return sum(Signal.grab_values(lines)) + + +def part2(lines: Iterator[str]) -> list[str]: + return Signal.draw(lines, 40, 6) + + +class Signal: + @staticmethod + def parse(line: str) -> None | int: + """ + Parses the a line into the two possible instructions. + May raise if the instructions was invalid + """ + match line.split(): + case ['noop']: + return None + case ['addx', value]: + return int(value) + case _: + raise Exception(f"Unknown line: {line}") + + @staticmethod + def cycles(lines: Iterator[str]) -> Iterator[int]: + """ + Cycles throw the instructions and yields a new value on each cycle + """ + register = 1 + for line in lines: + yield register + command = Signal.parse(line) + if command is not None: + yield register + register += command + + @staticmethod + def grab_values(lines: Iterator[str]) -> Iterator[int]: + for cycle, value in enumerate(Signal.cycles(lines), start=1): + if cycle in [20, 60, 100, 140, 180, 220]: + yield cycle * value + + @staticmethod + def draw(lines: Iterator[str], width: int, height: int) -> list[str]: + picture = "" + for cycle, sprite in enumerate(Signal.cycles(lines)): + crt_pos = cycle % width + if sprite - 1 <= crt_pos and crt_pos <= sprite + 1: + picture += '#' + else: + picture += ' ' + + if crt_pos == width - 1: + picture += '\n' + return picture.split('\n')[:height] diff --git a/advent/days/day10/test_solution.py b/advent/days/day10/test_solution.py new file mode 100644 index 0000000..82142a1 --- /dev/null +++ b/advent/days/day10/test_solution.py @@ -0,0 +1,38 @@ +from advent.common import utils + +from .solution import Signal, day_num, part1, part2 + + +def test_part1(): + lines = utils.read_data(day_num, 'test01.txt') + expected = 13140 + result = part1(lines) + assert result == expected + + +def test_part2(): + lines = utils.read_data(day_num, 'test01.txt') + expected = list(utils.read_data(day_num, 'expected.txt')) + result = part2(lines) + assert result == expected + + +def test_small(): + lines = utils.read_data(day_num, 'test02.txt') + expected = [1, 1, 1, 4, 4] + result = list(Signal.cycles(lines)) + assert result == expected + + +def test_grab_values(): + lines = utils.read_data(day_num, 'test01.txt') + expected = [420, 1140, 1800, 2940, 2880, 3960] + result = list(Signal.grab_values(lines)) + assert result == expected + + +def test_draw(): + lines = utils.read_data(day_num, 'test01.txt') + expected = list(utils.read_data(day_num, 'expected.txt')) + result = Signal.draw(lines, 40, 6) + assert result == expected