From affaf6e96f217c3225e6f8bfcf833c6b1af98d43 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 28 Oct 2021 17:54:52 +0200 Subject: [PATCH] 2019 day 24 part 1 --- 2019/aoc2019/day24.py | 58 ++++++++++++++++++++++++++++++++++++ 2019/tests/test_day24.py | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 2019/aoc2019/day24.py create mode 100644 2019/tests/test_day24.py diff --git a/2019/aoc2019/day24.py b/2019/aoc2019/day24.py new file mode 100644 index 0000000..9dced01 --- /dev/null +++ b/2019/aoc2019/day24.py @@ -0,0 +1,58 @@ +from typing import TextIO, Iterable, Tuple + + +def read_board(data: TextIO) -> Tuple[Tuple[bool]]: + return tuple( + tuple(c == '#' for c in line.strip()) + for line in data + ) + + +def flatten(it: Iterable[Iterable]) -> Iterable: + for item in it: + yield from item + + +def neighbours(board: Tuple[Tuple[bool]], x: int, y: int) -> int: + n = 0 + + if x > 0 and board[y][x - 1]: + n += 1 + + if x + 1 < len(board[0]) and board[y][x + 1]: + n += 1 + + if y > 0 and board[y - 1][x]: + n += 1 + + if y + 1 < len(board) and board[y + 1][x]: + n += 1 + + return n + + +def advance_board(board: Tuple[Tuple[bool]]) -> Tuple[Tuple[bool]]: + def create_row(y: int, row: Tuple[bool]): + new_row = [] + for x, live in enumerate(row): + if live: + new_row.append(neighbours(board, x, y) == 1) + else: + new_row.append(neighbours(board, x, y) in [1, 2]) + + return tuple(new_row) + + return tuple(create_row(y, row) for y, row in enumerate(board)) + + +def part1(data: TextIO) -> int: + board = read_board(data) + + seen = set(board) + + while True: + board = advance_board(board) + if board in seen: + return sum(2 ** i for i, b in enumerate(flatten(board)) if b) + + seen.add(board) diff --git a/2019/tests/test_day24.py b/2019/tests/test_day24.py new file mode 100644 index 0000000..51426b0 --- /dev/null +++ b/2019/tests/test_day24.py @@ -0,0 +1,64 @@ +import io + +import pytest + +from aoc2019.day24 import read_board, advance_board, part1 + +SAMPLE_START = """\ +....# +#..#. +#..## +..#.. +#.... +""" + +SAMPLE_STATES = """\ +....# +#..#. +#..## +..#.. +#.... + +#..#. +####. +###.# +##.## +.##.. + +##### +....# +....# +...#. +#.### + +#.... +####. +...## +#.##. +.##.# + +####. +....# +##..# +..... +##... +""".split("\n\n") + + +@pytest.mark.parametrize("cycles,state", enumerate(SAMPLE_STATES)) +def test_evolution_part1(cycles: int, state: str) -> None: + with io.StringIO(SAMPLE_START) as f: + board = read_board(f) + + with io.StringIO(state) as f: + final_state = read_board(f) + + for _ in range(cycles): + board = advance_board(board) + + assert board == final_state + + +def test_sample_part1() -> None: + with io.StringIO(SAMPLE_START) as f: + assert part1(f) == 2129920