Skip to content

Commit

Permalink
feat: add 2023 day 09
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelblijleven committed Dec 9, 2023
1 parent 2768264 commit d3e4b2c
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
78 changes: 78 additions & 0 deletions src/adventofcode/year_2023/day_09_2023.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import re
from functools import partial
from itertools import pairwise
from operator import itemgetter
from typing import Iterable

from adventofcode.util.exceptions import SolutionNotFoundError
from adventofcode.registry.decorators import register_solution
from adventofcode.util.input_helpers import get_input_for_day


pattern = re.compile("-?\\d+")


def parse_sequence(sequence: str) -> Iterable[int]:
return map(int, pattern.findall(sequence))


def parse_sequence_backwards(sequence: str) -> Iterable[int]:
return reversed(list(map(int, pattern.findall(sequence))))


def parse_input(data: list[str]) -> Iterable[Iterable[int]]:
return map(parse_sequence, data)


def parse_input_reversed(data: list[str]) -> Iterable[Iterable[int]]:
return map(parse_sequence_backwards, data)


def find_next_in_sequence(sequence: Iterable[int], lines: list[list[int]] | None) -> int:
numbers = list(sequence)
lines = [numbers] if lines is None or len(lines) == 0 else lines
differences = [y-x for (x, y) in pairwise(numbers)]
lines.append(differences)

if any(differences):
return find_next_in_sequence(differences, lines)

return sum(map(itemgetter(-1), lines))


def solve_part_one(data: list[str]) -> int:
parsed_input = parse_input(data)
find_next = partial(find_next_in_sequence, lines=None)
return sum(map(find_next, parsed_input))


def solve_part_two(data: list[str]) -> int:
parsed_input = parse_input_reversed(data)
find_next = partial(find_next_in_sequence, lines=None)
return sum(map(find_next, parsed_input))


@register_solution(2023, 9, 1)
def part_one(input_data: list[str]):
answer = solve_part_one(input_data)

if not answer:
raise SolutionNotFoundError(2023, 9, 1)

return answer


@register_solution(2023, 9, 2)
def part_two(input_data: list[str]):
answer = solve_part_two(input_data)

if not answer:
raise SolutionNotFoundError(2023, 9, 2)

return answer


if __name__ == '__main__':
data = get_input_for_day(2023, 9)
part_one(data)
part_two(data)
45 changes: 45 additions & 0 deletions tests/adventofcode/year_2023/test_day_09_2023.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest

from adventofcode.year_2023.day_09_2023 import part_two, part_one, parse_input, parse_sequence, find_next_in_sequence

test_input = [
"0 3 6 9 12 15",
"1 3 6 10 15 21",
"10 13 16 21 30 45",
]


@pytest.mark.parametrize(["sequence", "expected"], [
("0 3 6 9 12 15", [0, 3, 6, 9, 12, 15]),
("1 3 6 10 15 21", [1, 3, 6, 10, 15, 21]),
("10 13 16 21 30 45", [10, 13, 16, 21, 30, 45]),
("-1 -20 -300 400", [-1, -20, -300, 400]),
("5 1 -3 -7 -11 -15 -19 -23 -27 -31 -35 -39 -43 -47 -51 -55 -59 -63 -67 -71 -75", [5, 1, -3, -7, -11, -15, -19, -23, -27, -31, -35, -39, -43, -47, -51, -55, -59, -63, -67, -71, -75]),
])
def test_parse_sequence(sequence, expected):
assert list(parse_sequence(sequence)) == expected


def test_parse_input():
assert len(list(parse_input(test_input))) == 3


@pytest.mark.parametrize(["sequence", "expected"], [
([13, 23, 46, 97, 206, 436, 919, 1924, 3971, 8016, 15765, 30243, 56875, 105604, 195153, 361805, 677725, 1289089,
2494076, 4898137, 9713336], 19316320),
([-7, 6, 44, 130, 309, 672, 1404, 2864, 5712, 11113, 21082, 39112, 71386, 129156, 233312, 422773, 769075,
1400300, 2538072, 4551386, 8029995], 13877188
),
([5, 1, -3, -7, -11, -15, -19, -23, -27, -31, -35, -39, -43, -47, -51, -55, -59, -63, -67, -71, -75,
], -79)
])
def test_find_next_in_sequence(sequence, expected):
assert find_next_in_sequence(sequence, []) == expected


def test_part_one():
assert part_one(test_input) == 114


def test_part_two():
assert part_two(test_input) == 'x'

0 comments on commit d3e4b2c

Please sign in to comment.