diff options
| -rw-r--r-- | 2025/03/.gitignore | 1 | ||||
| -rw-r--r-- | 2025/03/Makefile | 1 | ||||
| -rw-r--r-- | 2025/03/puzzles.c | 48 | ||||
| -rw-r--r-- | 2025/04/.gitignore | 1 | ||||
| -rw-r--r-- | 2025/04/Makefile | 1 | ||||
| -rw-r--r-- | 2025/04/puzzles.py | 95 | ||||
| -rwxr-xr-x | 2025/05/puzzle-1.awk | 19 | ||||
| -rwxr-xr-x | 2025/05/puzzle-2.awk | 31 | ||||
| -rwxr-xr-x | 2025/06/puzzle-1.awk | 20 | ||||
| -rwxr-xr-x | 2025/06/puzzle-2.sh | 27 | ||||
| -rwxr-xr-x | 2025/07/puzzle-1.py | 23 | ||||
| -rwxr-xr-x | 2025/07/puzzle-2.py | 31 |
12 files changed, 298 insertions, 0 deletions
diff --git a/2025/03/.gitignore b/2025/03/.gitignore new file mode 100644 index 0000000..60d075d --- /dev/null +++ b/2025/03/.gitignore @@ -0,0 +1 @@ +puzzle-[12] diff --git a/2025/03/Makefile b/2025/03/Makefile new file mode 100644 index 0000000..de3f940 --- /dev/null +++ b/2025/03/Makefile @@ -0,0 +1 @@ +include ../../Makefiles/c.mk diff --git a/2025/03/puzzles.c b/2025/03/puzzles.c new file mode 100644 index 0000000..9bd68ee --- /dev/null +++ b/2025/03/puzzles.c @@ -0,0 +1,48 @@ +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef PART1 + #define DIGITS ((size_t)(2)) +#else + #define DIGITS ((size_t)(12)) +#endif + +int +main(void) +{ + FILE *fp = fopen("input", "r"); + if (fp == nullptr) + err(EXIT_FAILURE, "failed to open input"); + + char *buf = nullptr; + size_t acc, bufsz; + ssize_t n; + + acc = bufsz = 0; + + while ((n = getline(&buf, &bufsz, fp)) != -1) { + if (buf[n - 1] == '\n') + buf[--n] = 0; + + char digits[DIGITS + 1]; + memcpy(digits, buf, DIGITS); + digits[DIGITS] = 0; + + for (size_t i = 1; i < n - DIGITS + 1; i++) { + for (size_t j = 0; j < DIGITS; j++) { + if (buf[i + j] > digits[j]) + memcpy(digits + j, buf + i + j, DIGITS - j); + } + } + + acc += (size_t)strtol(digits, nullptr, 10); + } + if (ferror(fp)) + err(EXIT_FAILURE, "failed to read record"); + + fclose(fp); + printf("%zu\n", acc); + return EXIT_SUCCESS; +} diff --git a/2025/04/.gitignore b/2025/04/.gitignore new file mode 100644 index 0000000..ffc46fe --- /dev/null +++ b/2025/04/.gitignore @@ -0,0 +1 @@ +puzzle-[12].py diff --git a/2025/04/Makefile b/2025/04/Makefile new file mode 100644 index 0000000..0a4e980 --- /dev/null +++ b/2025/04/Makefile @@ -0,0 +1 @@ +include ../../Makefiles/py.mk diff --git a/2025/04/puzzles.py b/2025/04/puzzles.py new file mode 100644 index 0000000..3558269 --- /dev/null +++ b/2025/04/puzzles.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 + +import itertools +from typing import Generator, Iterator, Self, TextIO + + +class Grid: + @classmethod + def from_file(cls, f: TextIO) -> Self: + g = Grid() + g._grid = mkmap( + [[c for c in l if c != '\n'] for l in f.readlines()]) + return g + + def in_bounds_p(self, z: complex) -> bool: + return ( + 0 <= z.real < len(self._grid[0]) + and 0 <= z.imag < len(self._grid) + ) + + def accessablep(self, z: complex) -> bool: + return self[z] is not None and self[z] < 4 + + def indicies(self) -> Iterator[complex]: + return itertools.starmap(complex, itertools.product( + range(len(self._grid[0])), + range(len(self._grid)), + )) + + def neighbors(self, z: complex) -> Generator[complex, None, None]: + for Δ in ( + -1-1j, -1, -1+1j, + 0-1j, 0+1j, + +1-1j, +1, +1+1j, + ): + if self.in_bounds_p(z + Δ): + yield z + Δ + + def __getitem__(self, z: complex) -> int | None: + return self._grid[int(z.real)][int(z.imag)] + + def __setitem__(self, z: complex, n: int | None) -> None: + self._grid[int(z.real)][int(z.imag)] = n + + +def mkmap(xs: list[list[str]]) -> list[list[int]]: + def get(pos: complex) -> str: + r, i = map(int, (pos.real, pos.imag)) + if 0 <= r < len(xs[0]) and 0 <= i < len(xs): + return xs[r][i] + return '.' + + return [ + [ + sum(get(complex(i, j) + Δ) == '@' for Δ in [ + -1-1j, -1, -1+1j, + 0-1j, 0+1j, + +1-1j, +1, +1+1j, + ]) + if get(complex(i, j)) == '@' + else None + for j in range(len(xs[i])) + ] + for i in range(len(xs)) + ] + + +def main() -> None: + with open('input', 'r') as f: + grid = Grid.from_file(f) + + if PUZZLE_PART == 1: + acc = sum(grid.accessablep(z) for z in grid.indicies()) + else: + acc = 0 + while True: + breakp = True + for z in grid.indicies(): + if not grid.accessablep(z): + continue + breakp = False + acc += 1 + grid[z] = None + for p in grid.neighbors(z): + if grid[p] is not None: + grid[p] -= 1 + + if breakp: + break + + print(acc) + + +if __name__ == '__main__': + main() diff --git a/2025/05/puzzle-1.awk b/2025/05/puzzle-1.awk new file mode 100755 index 0000000..acfe21b --- /dev/null +++ b/2025/05/puzzle-1.awk @@ -0,0 +1,19 @@ +#!/usr/bin/awk -f + +BEGIN { FS = "-" } + +NF == 2 { + xs[NR, 1] = $1 + xs[NR, 2] = $2 +} + +NF == 1 { + for (i = 1; i <= length(xs) / 2; i++) { + if ($1 >= xs[i, 1] && $1 <= xs[i, 2]) { + cnt++ + break + } + } +} + +END { print cnt } diff --git a/2025/05/puzzle-2.awk b/2025/05/puzzle-2.awk new file mode 100755 index 0000000..3dfc661 --- /dev/null +++ b/2025/05/puzzle-2.awk @@ -0,0 +1,31 @@ +#!/usr/bin/gawk -f + +function rangecmp(i1, v1, i2, v2) +{ + return v1[1] - v2[1] +} + +function max(x, y) +{ + return x > y ? x : y +} + +BEGIN { FS = "-" } + +NF == 2 { + xs[NR][1] = $1 + xs[NR][2] = $2 +} + +END { + asort(xs, xs, "rangecmp") + for (i in xs) { + if (xs[i][2] <= m) + continue + cnt += xs[i][2] - max(xs[i][1], m) + if (xs[i][1] > m) + cnt++ + m = xs[i][2] + } + print cnt +} diff --git a/2025/06/puzzle-1.awk b/2025/06/puzzle-1.awk new file mode 100755 index 0000000..4bb4338 --- /dev/null +++ b/2025/06/puzzle-1.awk @@ -0,0 +1,20 @@ +#!/usr/bin/awk -f + +NR == 1 { + for (i = 1; i <= NF; i++) + xs[i, 2] = 1 +} + +!/[+*]/ { + for (i = 1; i <= NF; i++) { + xs[i, 1] += $i + xs[i, 2] *= $i + } +} + +/[+*]/ { + for (i = 1; i <= NF; i++) + total += xs[i, $i == "+" ? 1 : 2] +} + +END { print total } diff --git a/2025/06/puzzle-2.sh b/2025/06/puzzle-2.sh new file mode 100755 index 0000000..cba270f --- /dev/null +++ b/2025/06/puzzle-2.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +{ + printf '(' + for i in $(seq "$(head -n1 input | wc -c)") + do + num="$(cut -c $i input | paste -sd '')" + num="${num%${num##*[![:space:]]}}" + + case "$num" in + *[+*]) + test -n "$op" && printf ') + (' + op="${num#${num%?}}" + num="${num%?}" + printf '%d %s ' $num "$op" + ;; + '') + test "$op" = + + printf '%d' $? + ;; + *) + printf '%d %s ' $num "$op" + ;; + esac + done + printf ')\n' +} | bc diff --git a/2025/07/puzzle-1.py b/2025/07/puzzle-1.py new file mode 100755 index 0000000..0c30dfa --- /dev/null +++ b/2025/07/puzzle-1.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + + +def main() -> None: + with open('input', 'r') as f: + grid = tuple(tuple(x.strip()) for x in f.readlines()) + + xs = set() + xs.add(grid[0].index('S')) + cnt = 0 + + for row in grid[1:]: + for i, ch in enumerate(row): + if ch == '^' and i in xs: + cnt += 1 + xs.remove(i) + xs.add(i - 1) + xs.add(i + 1) + + print(cnt) + +if __name__ == '__main__': + main() diff --git a/2025/07/puzzle-2.py b/2025/07/puzzle-2.py new file mode 100755 index 0000000..3695889 --- /dev/null +++ b/2025/07/puzzle-2.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 + +import collections +import functools + + +Pos = collections.namedtuple('Pos', ['x', 'y']) + + +def main() -> None: + with open('input', 'r') as f: + grid = tuple(tuple(x.strip()) for x in f.readlines()) + + pos = Pos(grid[0].index('S'), 0) + print(npaths(grid, pos)) + + +@functools.cache +def npaths(grid: list[list[str]], pos: Pos) -> int: + if pos.y == len(grid): + return 1 + if grid[pos.y][pos.x] == '^': + return ( + npaths(grid, Pos(pos.x - 1, pos.y)) + + npaths(grid, Pos(pos.x + 1, pos.y)) + ) + return npaths(grid, Pos(pos.x, pos.y + 1)) + + +if __name__ == '__main__': + main() |