diff --git a/aoc_cas/aoc2023/day1.py b/aoc_cas/aoc2023/day1.py index 44c01b0..ca55e45 100644 --- a/aoc_cas/aoc2023/day1.py +++ b/aoc_cas/aoc2023/day1.py @@ -36,6 +36,6 @@ def part_b(data) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(2023, 1) + solve_with_example_data(2023, 1) diff --git a/aoc_cas/aoc2023/day10.py b/aoc_cas/aoc2023/day10.py index aa6664c..b532b6a 100644 --- a/aoc_cas/aoc2023/day10.py +++ b/aoc_cas/aoc2023/day10.py @@ -106,6 +106,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=10) + solve_with_example_data(year=2023, day=10) diff --git a/aoc_cas/aoc2023/day11.py b/aoc_cas/aoc2023/day11.py index 960272e..bb17944 100644 --- a/aoc_cas/aoc2023/day11.py +++ b/aoc_cas/aoc2023/day11.py @@ -59,6 +59,6 @@ def part_b(data: str, expansion: int = 1000000) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=11) + solve_with_example_data(year=2023, day=11) diff --git a/aoc_cas/aoc2023/day12.py b/aoc_cas/aoc2023/day12.py index f09601a..33424f1 100644 --- a/aoc_cas/aoc2023/day12.py +++ b/aoc_cas/aoc2023/day12.py @@ -42,6 +42,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=12) + solve_with_example_data(year=2023, day=12) diff --git a/aoc_cas/aoc2023/day13.py b/aoc_cas/aoc2023/day13.py index 19418e6..4fc45e7 100644 --- a/aoc_cas/aoc2023/day13.py +++ b/aoc_cas/aoc2023/day13.py @@ -64,7 +64,7 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=13) + solve_with_example_data(year=2023, day=13) ["#.##..##." "..#.##.#." "##......#" "##......#" "..#.##.#." "..##..##." "#.#.##.#."] diff --git a/aoc_cas/aoc2023/day14.py b/aoc_cas/aoc2023/day14.py index 6829b77..314b980 100644 --- a/aoc_cas/aoc2023/day14.py +++ b/aoc_cas/aoc2023/day14.py @@ -104,6 +104,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=14) + solve_with_example_data(year=2023, day=14) diff --git a/aoc_cas/aoc2023/day15.py b/aoc_cas/aoc2023/day15.py index a4ac1f4..6bb8c35 100644 --- a/aoc_cas/aoc2023/day15.py +++ b/aoc_cas/aoc2023/day15.py @@ -44,6 +44,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=15) + solve_with_example_data(year=2023, day=15) diff --git a/aoc_cas/aoc2023/day16.py b/aoc_cas/aoc2023/day16.py index cbc26cb..9f2567c 100644 --- a/aoc_cas/aoc2023/day16.py +++ b/aoc_cas/aoc2023/day16.py @@ -75,6 +75,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=16) + solve_with_example_data(year=2023, day=16) diff --git a/aoc_cas/aoc2023/day17.py b/aoc_cas/aoc2023/day17.py index 29436c5..05b6246 100644 --- a/aoc_cas/aoc2023/day17.py +++ b/aoc_cas/aoc2023/day17.py @@ -64,6 +64,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=17) + solve_with_example_data(year=2023, day=17) diff --git a/aoc_cas/aoc2023/day18.py b/aoc_cas/aoc2023/day18.py index 2ecc99a..0446261 100644 --- a/aoc_cas/aoc2023/day18.py +++ b/aoc_cas/aoc2023/day18.py @@ -53,6 +53,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=18) + solve_with_example_data(year=2023, day=18) diff --git a/aoc_cas/aoc2023/day2.py b/aoc_cas/aoc2023/day2.py index 0f8b7c0..e2ba232 100644 --- a/aoc_cas/aoc2023/day2.py +++ b/aoc_cas/aoc2023/day2.py @@ -40,6 +40,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=2) + solve_with_example_data(year=2023, day=2) diff --git a/aoc_cas/aoc2023/day3.py b/aoc_cas/aoc2023/day3.py index 344b266..4efea33 100644 --- a/aoc_cas/aoc2023/day3.py +++ b/aoc_cas/aoc2023/day3.py @@ -41,6 +41,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=3) + solve_with_example_data(year=2023, day=3) diff --git a/aoc_cas/aoc2023/day4.py b/aoc_cas/aoc2023/day4.py index 7d8c981..a3b9b49 100644 --- a/aoc_cas/aoc2023/day4.py +++ b/aoc_cas/aoc2023/day4.py @@ -27,6 +27,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=4) + solve_with_example_data(year=2023, day=4) diff --git a/aoc_cas/aoc2023/day5.py b/aoc_cas/aoc2023/day5.py index dc836ab..89ee56f 100644 --- a/aoc_cas/aoc2023/day5.py +++ b/aoc_cas/aoc2023/day5.py @@ -136,7 +136,7 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=5) + solve_with_example_data(year=2023, day=5) data = get_data(year=2023, day=5) diff --git a/aoc_cas/aoc2023/day6.py b/aoc_cas/aoc2023/day6.py index b510a98..3b3c7b0 100644 --- a/aoc_cas/aoc2023/day6.py +++ b/aoc_cas/aoc2023/day6.py @@ -23,6 +23,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=6) + solve_with_example_data(year=2023, day=6) diff --git a/aoc_cas/aoc2023/day7.py b/aoc_cas/aoc2023/day7.py index a5a7b60..f013c59 100644 --- a/aoc_cas/aoc2023/day7.py +++ b/aoc_cas/aoc2023/day7.py @@ -79,6 +79,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=7) + solve_with_example_data(year=2023, day=7) diff --git a/aoc_cas/aoc2023/day8.py b/aoc_cas/aoc2023/day8.py index 00972bf..4b8a9f2 100644 --- a/aoc_cas/aoc2023/day8.py +++ b/aoc_cas/aoc2023/day8.py @@ -46,6 +46,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=8) + solve_with_example_data(year=2023, day=8) diff --git a/aoc_cas/aoc2023/day9.py b/aoc_cas/aoc2023/day9.py index 6fce14a..90ca95d 100644 --- a/aoc_cas/aoc2023/day9.py +++ b/aoc_cas/aoc2023/day9.py @@ -25,6 +25,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2023, day=9) + solve_with_example_data(year=2023, day=9) diff --git a/aoc_cas/aoc2024/day1.py b/aoc_cas/aoc2024/day1.py index 8956729..8fdb886 100644 --- a/aoc_cas/aoc2024/day1.py +++ b/aoc_cas/aoc2024/day1.py @@ -24,6 +24,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2024, day=1) + solve_with_example_data(year=2024, day=1) diff --git a/aoc_cas/aoc2024/day2.py b/aoc_cas/aoc2024/day2.py index d586fc2..c7541d8 100644 --- a/aoc_cas/aoc2024/day2.py +++ b/aoc_cas/aoc2024/day2.py @@ -43,6 +43,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2024, day=2) + solve_with_example_data(year=2024, day=2) diff --git a/aoc_cas/aoc2024/day3.py b/aoc_cas/aoc2024/day3.py index bfeb633..632cb59 100644 --- a/aoc_cas/aoc2024/day3.py +++ b/aoc_cas/aoc2024/day3.py @@ -16,6 +16,6 @@ def part_b(data: str) -> int: if __name__ == "__main__": - from aoc_cas.util import solve_with_examples + from aoc_cas.util import solve_with_example_data - solve_with_examples(year=2024, day=3) + solve_with_example_data(year=2024, day=3) diff --git a/aoc_cas/aoc2024/day5.py b/aoc_cas/aoc2024/day5.py new file mode 100644 index 0000000..d208aef --- /dev/null +++ b/aoc_cas/aoc2024/day5.py @@ -0,0 +1,69 @@ +import typing as t +from collections import defaultdict + +Update = list[int] +IsOrdered = t.Callable[[int, int], bool] + + +def _build_rule(rule_data: str) -> IsOrdered: + rule: dict[int, set[int]] = defaultdict(set) + for line in rule_data.splitlines(): + n1, n2 = map(int, line.split("|")) + rule[n1].add(n2) + + def _is_before(n1: int, n2: int) -> bool: + if n2 in rule[n1]: + return True + return False + + return _is_before + + +def _build_page_updates(page_data: str) -> list[Update]: + page_updates = [] + for line in page_data.splitlines(): + page_updates.append(list(map(int, line.split(",")))) + return page_updates + + +def _parse_data(data: str) -> tuple[IsOrdered, list[Update]]: + rule_data, page_data = data.split("\n\n") + return _build_rule(rule_data), _build_page_updates(page_data) + + +def _update_order_is_valid(update: Update, rule: IsOrdered) -> bool: + return all(rule(n1, n2) for n1, n2 in zip(update, update[1:])) + + +def part_a(data: str) -> int: + rule, updates = _parse_data(data) + middle_page_sum = 0 + for update in updates: + if _update_order_is_valid(update, rule): + middle_page_sum += update[len(update) // 2] + return middle_page_sum + + +def part_b(data: str) -> int: + rule, updates = _parse_data(data) + + def fix_page_order(update: Update) -> Update: + # Bubble sort it + for k in range(1, len(update)): + for i in range(len(update) - k): + if not rule(update[i], update[i + 1]): + update[i], update[i + 1] = update[i + 1], update[i] + return update + + middle_page_sum = 0 + for update in updates: + if not _update_order_is_valid(update, rule): + update = fix_page_order(update) + middle_page_sum += update[len(update) // 2] + return middle_page_sum + + +if __name__ == "__main__": + from aoc_cas.util import solve_with_example_data + + solve_with_example_data(year=2024, day=5) diff --git a/aoc_cas/cli.py b/aoc_cas/cli.py index ab94e2e..f48ba9f 100644 --- a/aoc_cas/cli.py +++ b/aoc_cas/cli.py @@ -24,8 +24,10 @@ def solve(year: int, day: int, submit: bool) -> None: print(f"PartA: {part_a_result}") print(f"PartB: {part_b_result}") if submit: - puzzle.answer_a = part_a_result - puzzle.answer_b = part_b_result + if part_a_result is not None: + puzzle.answer_a = part_a_result + if part_b_result is not None: + puzzle.answer_b = part_b_result @main.command() diff --git a/aoc_cas/util.py b/aoc_cas/util.py index 3bbd387..b88a967 100644 --- a/aoc_cas/util.py +++ b/aoc_cas/util.py @@ -8,7 +8,18 @@ def load_module(year: int, day: int): return importlib.import_module(module_name) -def solve_with_examples(year: int, day: int) -> None: +def solve_with_real_input_data(year: int, day: int) -> None: + puzzle = Puzzle(year, day) + mod = load_module(year, day) + part_a_result = str(mod.part_a(puzzle.input_data)) + part_b_result = str(mod.part_b(puzzle.input_data)) + + print(f"\nReal data input\n") + print(f"[Part A] {part_a_result}") + print(f"[Part B] {part_b_result}") + + +def solve_with_example_data(year: int, day: int) -> None: puzzle = Puzzle(year, day) print(f"Testing example data") diff --git a/tests/fixtures/2024/5.txt b/tests/fixtures/2024/5.txt new file mode 100644 index 0000000..6022c95 --- /dev/null +++ b/tests/fixtures/2024/5.txt @@ -0,0 +1,30 @@ +47|53 +97|13 +97|61 +97|47 +75|29 +61|13 +75|53 +29|13 +97|29 +53|29 +61|53 +97|53 +61|29 +47|13 +75|47 +97|75 +47|61 +75|61 +47|29 +75|13 +53|13 + +75,47,61,53,29 +97,61,53,29,13 +75,29,13 +75,97,47,61,53 +61,13,29 +97,13,75,29,47 +143 +123 \ No newline at end of file