From b4195baae3b36bd997a97d24fd5e0ab38dcd5595 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Sun, 12 Dec 2021 06:56:03 +0100 Subject: Add libaoc --- .gitignore | 1 + 2021/04/puzzles.py | 7 ++++--- 2021/09/puzzle-1.py | 42 +++++++++++++++++++++++------------------- 2021/09/puzzle-2.py | 10 +++++----- 2021/11/puzzles.py | 18 ++++++------------ README.rst | 14 ++++++++++++++ libaoc.py | 26 ++++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 39 deletions(-) create mode 100644 libaoc.py diff --git a/.gitignore b/.gitignore index 538d26d..29bc987 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +__pycache__/ .clang-format puzzle-[12] tmp[12].* diff --git a/2021/04/puzzles.py b/2021/04/puzzles.py index 20036e0..46dfa05 100644 --- a/2021/04/puzzles.py +++ b/2021/04/puzzles.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 -board = list[list[int]] +from libaoc import flatten, map2d, matrix + +board = matrix[int] last: board = [] @@ -42,8 +44,7 @@ def main() -> None: # START PART 2 boards = list(filter(lambda b: not bingo(b), boards)) # END PART 2 - - print(num * sum(map(lambda x: sum(filter(lambda n: n != -1, x)), last))) + print(num * sum(flatten(map2d(lambda n: 0 if n == -1 else n, last)))) if __name__ == "__main__": diff --git a/2021/09/puzzle-1.py b/2021/09/puzzle-1.py index 5ab2f45..be333a5 100755 --- a/2021/09/puzzle-1.py +++ b/2021/09/puzzle-1.py @@ -1,29 +1,33 @@ #!/usr/bin/env python3 +from itertools import product + +from libaoc import read_int_matrix + + def main() -> None: with open("input", "r", encoding="utf-8") as f: - data = list(map(lambda l: [int(n) for n in l.strip()], f.readlines())) + data = read_int_matrix(f) acc = 0 - rows = len(data[0]) - cols = len(data) - - for i in range(cols): - for j in range(rows): - if ( - i != 0 - and data[i - 1][j] <= data[i][j] - or i != cols - 1 - and data[i + 1][j] <= data[i][j] - or j != 0 - and data[i][j - 1] <= data[i][j] - or j != rows - 1 - and data[i][j + 1] <= data[i][j] - ): - continue - - acc += data[i][j] + 1 + rows = len(data) + cols = len(data[0]) + + for i, j in product(range(rows), range(cols)): + if ( + i != 0 + and data[i - 1][j] <= data[i][j] + or i != cols - 1 + and data[i + 1][j] <= data[i][j] + or j != 0 + and data[i][j - 1] <= data[i][j] + or j != rows - 1 + and data[i][j + 1] <= data[i][j] + ): + continue + + acc += data[i][j] + 1 print(acc) diff --git a/2021/09/puzzle-2.py b/2021/09/puzzle-2.py index d435f7c..72e0752 100755 --- a/2021/09/puzzle-2.py +++ b/2021/09/puzzle-2.py @@ -9,17 +9,17 @@ from functools import reduce from itertools import product from operator import mul -matrix = list[list[int]] +from libaoc import matrix, read_int_matrix -def is_basin(grid: matrix, row: int, col: int) -> bool: +def is_basin(grid: matrix[int], row: int, col: int) -> bool: return ( not ((row < 0 or row > len(grid) - 1) or (col < 0 or col > len(grid[0]) - 1)) and grid[row][col] != 9 ) -def floodfill(grid: matrix, row: int, col: int) -> int: +def floodfill(grid: matrix[int], row: int, col: int) -> int: if row < 0 or row > len(grid) - 1 or col < 0 or col > len(grid[0]) - 1 or grid[row][col] == 9: return 0 @@ -43,7 +43,7 @@ def floodfill(grid: matrix, row: int, col: int) -> int: return size -def solve(grid: matrix) -> int: +def solve(grid: matrix[int]) -> int: return reduce( mul, sorted( @@ -59,7 +59,7 @@ def solve(grid: matrix) -> int: def main() -> None: with open("input", "r", encoding="utf-8") as f: - print(solve(list(map(lambda l: [int(n) for n in l.strip()], f.readlines())))) + print(solve(read_int_matrix(f))) if __name__ == "__main__": diff --git a/2021/11/puzzles.py b/2021/11/puzzles.py index ad1fa05..19fb534 100644 --- a/2021/11/puzzles.py +++ b/2021/11/puzzles.py @@ -1,16 +1,13 @@ #!/usr/bin/env python3 -# START PART 1 -from itertools import product -# END PART 1 START PART 2 from itertools import chain, count, product -# END PART 2 -matrix = list[list[int]] +from libaoc import map2d, matrix, read_int_matrix + rows, cols = -1, -1 -def flash(grid: matrix, i: int, j: int) -> int: +def flash(grid: matrix[int], i: int, j: int) -> int: acc = 1 grid[i][j] = -1 @@ -29,7 +26,7 @@ def main() -> None: global rows, cols with open("input", "r", encoding="utf-8") as f: - grid = list(map(lambda l: [int(n) for n in l.strip()], f.readlines())) + grid = read_int_matrix(f) rows = len(grid) cols = len(grid[0]) @@ -40,8 +37,7 @@ def main() -> None: # END PART 1 START PART 2 for step in count(1): # END PART 2 - for i, j in product(range(rows), range(cols)): - grid[i][j] += 1 + grid = list(map2d(lambda n: n + 1, grid, list)) for i, j in product(range(rows), range(cols)): if grid[i][j] > 9: @@ -53,9 +49,7 @@ def main() -> None: return # END PART 2 - for i, j in product(range(rows), range(cols)): - if grid[i][j] == -1: - grid[i][j] = 0 + grid = list(map2d(lambda n: 0 if n == -1 else n, grid, list)) # START PART 1 print(acc) diff --git a/README.rst b/README.rst index de11e31..7b9e695 100644 --- a/README.rst +++ b/README.rst @@ -18,3 +18,17 @@ the "puzzles.ext" file as it's required to get the "puzzle-1.ext" and "puzzle-2. actually run properly. .. _Advent of Code: https://adventofcode.com + + +Running Code +------------ + +Some of the solutions in this repo make use of ``libaoc``. In order to run these solutions you need +to add the directory of the library to the ``PYTHONPATH`` environment variable. In other words, +instead of doing this:: + + $ ./puzzle-1.py + +You must do this:: + + $ PYTHONPATH=../../ ./puzzle-1.py diff --git a/libaoc.py b/libaoc.py new file mode 100644 index 0000000..1316691 --- /dev/null +++ b/libaoc.py @@ -0,0 +1,26 @@ +from io import TextIOWrapper +from typing import Any, Callable, Iterable, Iterator, Optional, TypeVar + +S = TypeVar("S") +T = TypeVar("T") +matrix = list[list[T]] + + +def flatten(iter: Iterable[Any]) -> Iterator[Any]: + if hasattr(iter, "__iter__") and type(iter) != str: + for i in iter: + yield from flatten(i) + else: + yield iter + + +def read_int_matrix(f: TextIOWrapper) -> matrix[int]: + return list(map(lambda l: [int(n) for n in l.strip()], f.readlines())) + + +def map2d( + func: Callable[[Any], Any], + iter: Iterable[Iterable[Any]], + const: Optional[Callable[[T], S]] = lambda x: x, +) -> map: + return map(lambda i: const(map(func, i)), iter) -- cgit v1.2.3