diff --git a/2025/d08/ex1/ex1.py b/2025/d08/ex1/ex1.py index 11f81e5..e97e931 100755 --- a/2025/d08/ex1/ex1.py +++ b/2025/d08/ex1/ex1.py @@ -1,9 +1,8 @@ #!/usr/bin/env python import collections -import functools import itertools -import operator +import math import sys from collections.abc import Iterable from typing import Generic, Hashable, NamedTuple, TypeVar @@ -105,9 +104,7 @@ def solve(input: list[str]) -> int: circuit_sizes = collections.Counter( {r: len(val) for r, val in connected.sets().items()} ) - return functools.reduce( - operator.mul, (size for _, size in circuit_sizes.most_common(3)) - ) + return math.prod(size for _, size in circuit_sizes.most_common(3)) def main() -> None: diff --git a/2025/d09/ex1/ex1.py b/2025/d09/ex1/ex1.py new file mode 100755 index 0000000..3aa94f9 --- /dev/null +++ b/2025/d09/ex1/ex1.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +import itertools +import sys +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + +def solve(input: list[str]) -> int: + def parse(input: list[str]) -> list[Point]: + return [Point(*map(int, line.split(","))) for line in input] + + def rectangle_area(p: Point, other: Point) -> int: + dx = abs(p.x - other.x) + dy = abs(p.y - other.y) + return (dx + 1) * (dy + 1) + + tiles = parse(input) + return max(rectangle_area(a, b) for a, b in itertools.combinations(tiles, 2)) + + +def main() -> None: + input = sys.stdin.read().splitlines() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2025/d09/ex1/input b/2025/d09/ex1/input new file mode 100644 index 0000000..23578e0 --- /dev/null +++ b/2025/d09/ex1/input @@ -0,0 +1,496 @@ +97918,50201 +97918,51425 +98247,51425 +98247,52647 +98195,52647 +98195,53859 +98005,53859 +98005,55071 +97872,55071 +97872,56297 +97835,56297 +97835,57522 +97759,57522 +97759,58659 +97171,58659 +97171,59849 +96924,59849 +96924,61075 +96832,61075 +96832,62278 +96613,62278 +96613,63385 +96045,63385 +96045,64538 +95663,64538 +95663,65837 +95705,65837 +95705,66999 +95314,66999 +95314,68121 +94816,68121 +94816,69159 +94132,69159 +94132,70235 +93557,70235 +93557,71392 +93150,71392 +93150,72594 +92813,72594 +92813,73464 +91858,73464 +91858,74283 +90857,74283 +90857,75827 +91050,75827 +91050,76622 +90026,76622 +90026,77623 +89334,77623 +89334,78461 +88419,78461 +88419,79592 +87898,79592 +87898,80529 +87121,80529 +87121,81258 +86103,81258 +86103,82506 +85676,82506 +85676,82951 +84373,82951 +84373,84417 +84129,84417 +84129,84738 +82744,84738 +82744,85431 +81740,85431 +81740,86272 +80874,86272 +80874,86984 +79898,86984 +79898,87707 +78934,87707 +78934,88651 +78132,88651 +78132,89825 +77471,89825 +77471,90048 +76152,90048 +76152,91026 +75332,91026 +75332,91113 +73969,91113 +73969,92433 +73319,92433 +73319,92653 +72052,92653 +72052,92817 +70779,92817 +70779,93561 +69793,93561 +69793,94429 +68844,94429 +68844,94816 +67683,94816 +67683,94825 +66387,94825 +66387,95504 +65340,95504 +65340,96215 +64286,96215 +64286,95778 +62890,95778 +62890,96609 +61858,96609 +61858,97235 +60751,97235 +60751,97506 +59554,97506 +59554,97496 +58306,97496 +58306,97162 +57021,97162 +57021,97638 +55863,97638 +55863,98017 +54678,98017 +54678,98087 +53458,98087 +53458,98404 +52250,98404 +52250,98467 +51023,98467 +51023,97591 +49799,97591 +49799,97549 +48594,97549 +48594,97447 +47393,97447 +47393,97559 +46176,97559 +46176,97590 +44957,97590 +44957,97139 +43794,97139 +43794,97718 +42484,97718 +42484,97235 +41328,97235 +41328,97025 +40129,97025 +40129,96569 +38986,96569 +38986,96439 +37767,96439 +37767,96227 +36561,96227 +36561,95775 +35425,95775 +35425,95708 +34160,95708 +34160,94873 +33165,94873 +33165,94442 +32030,94442 +32030,93853 +30961,93853 +30961,93475 +29801,93475 +29801,93145 +28610,93145 +28610,92571 +27533,92571 +27533,91778 +26580,91778 +26580,91054 +25599,91054 +25599,90700 +24392,90700 +24392,90098 +23330,90098 +23330,89610 +22181,89610 +22181,88575 +21422,88575 +21422,87836 +20456,87836 +20456,87257 +19358,87257 +19358,86584 +18325,86584 +18325,85761 +17416,85761 +17416,84396 +17026,84396 +17026,83497 +16219,83497 +16219,82724 +15282,82724 +15282,81812 +14488,81812 +14488,81287 +13242,81287 +13242,80044 +12835,80044 +12835,79273 +11850,79273 +11850,78300 +11117,78300 +11117,77140 +10654,77140 +10654,76100 +10032,76100 +10032,75292 +9038,75292 +9038,74404 +8140,74404 +8140,73087 +7988,73087 +7988,71995 +7455,71995 +7455,71036 +6653,71036 +6653,69869 +6271,69869 +6271,68669 +5984,68669 +5984,67752 +5008,67752 +5008,66446 +5011,66446 +5011,65435 +4213,65435 +4213,64209 +4035,64209 +4035,63114 +3426,63114 +3426,61827 +3512,61827 +3512,60715 +2925,60715 +2925,59521 +2657,59521 +2657,58341 +2305,58341 +2305,57063 +2555,57063 +2555,55868 +2321,55868 +2321,54631 +2469,54631 +2469,53453 +1978,53453 +1978,52239 +1840,52239 +1840,51023 +1568,51023 +1568,50187 +94581,50187 +94581,48595 +2489,48595 +2489,47360 +1948,47360 +1948,46149 +2099,46149 +2099,44932 +2173,44932 +2173,43745 +2490,43745 +2490,42544 +2663,42544 +2663,41373 +3007,41373 +3007,40066 +2674,40066 +2674,39008 +3523,39008 +3523,37778 +3604,37778 +3604,36502 +3567,36502 +3567,35540 +4584,35540 +4584,34126 +4191,34126 +4191,33194 +5204,33194 +5204,32063 +5639,32063 +5639,30930 +6073,30930 +6073,29848 +6623,29848 +6623,28717 +7070,28717 +7070,27492 +7350,27492 +7350,26613 +8281,26613 +8281,25390 +8594,25390 +8594,24514 +9492,24514 +9492,23522 +10191,23522 +10191,22173 +10377,22173 +10377,21180 +11097,21180 +11097,20343 +12018,20343 +12018,19523 +12942,19523 +12942,18816 +13983,18816 +13983,17981 +14858,17981 +14858,16809 +15376,16809 +15376,16068 +16353,16068 +16353,15030 +17038,15030 +17038,14301 +18019,14301 +18019,13410 +18855,13410 +18855,12559 +19733,12559 +19733,12152 +20957,12152 +20957,10852 +21506,10852 +21506,10788 +22952,10788 +22952,9988 +23871,9988 +23871,8781 +24548,8781 +24548,8442 +25771,8442 +25771,7748 +26780,7748 +26780,7638 +28098,7638 +28098,6597 +28936,6597 +28936,6634 +30295,6634 +30295,5530 +31137,5530 +31137,5119 +32291,5119 +32291,5171 +33611,5171 +33611,4750 +34745,4750 +34745,4394 +35901,4394 +35901,4192 +37101,4192 +37101,3248 +38105,3248 +38105,3209 +39349,3209 +39349,2909 +40529,2909 +40529,2965 +41774,2965 +41774,2208 +42884,2208 +42884,2578 +44163,2578 +44163,2700 +45391,2700 +45391,1938 +46543,1938 +46543,2387 +47786,2387 +47786,2473 +48995,2473 +48995,2002 +50202,2002 +50202,1582 +51430,1582 +51430,1775 +52649,1775 +52649,2210 +53841,2210 +53841,2166 +55067,2166 +55067,2369 +56270,2369 +56270,2715 +57447,2715 +57447,2376 +58742,2376 +58742,3117 +59840,3117 +59840,2894 +61140,2894 +61140,3742 +62185,3742 +62185,3817 +63425,3817 +63425,3989 +64648,3989 +64648,5057 +65573,5057 +65573,4922 +66910,4922 +66910,5185 +68120,5185 +68120,5964 +69117,5964 +69117,6674 +70128,6674 +70128,6710 +71460,6710 +71460,7450 +72454,7450 +72454,8385 +73327,8385 +73327,8392 +74729,8392 +74729,9508 +75475,9508 +75475,10041 +76576,10041 +76576,10869 +77480,10869 +77480,11720 +78357,11720 +78357,12429 +79335,12429 +79335,12852 +80550,12852 +80550,13833 +81313,13833 +81313,14720 +82144,14720 +82144,15684 +82895,15684 +82895,16530 +83752,16530 +83752,17162 +84838,17162 +84838,17952 +85773,17952 +85773,18787 +86668,18787 +86668,19898 +87235,19898 +87235,20534 +88399,20534 +88399,21819 +88718,21819 +88718,22937 +89233,22937 +89233,23968 +89861,23968 +89861,24660 +91036,24660 +91036,25849 +91424,25849 +91424,26916 +92004,26916 +92004,27802 +92933,27802 +92933,28832 +93616,28832 +93616,30336 +93275,30336 +93275,31169 +94394,31169 +94394,32316 +94816,32316 +94816,33403 +95397,33403 +95397,34581 +95737,34581 +95737,35916 +95557,35916 +95557,37120 +95737,37120 +95737,38230 +96258,38230 +96258,39290 +97047,39290 +97047,40627 +96600,40627 +96600,41738 +97237,41738 +97237,42902 +97667,42902 +97667,44190 +97201,44190 +97201,45331 +97913,45331 +97913,46539 +98110,46539 +98110,47754 +98296,47754 +98296,48987 +97943,48987 +97943,50201 diff --git a/2025/d09/ex2/ex2.py b/2025/d09/ex2/ex2.py new file mode 100755 index 0000000..fb2d2ac --- /dev/null +++ b/2025/d09/ex2/ex2.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python + +import itertools +import sys +from collections.abc import Iterator +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + +def solve(input: list[str]) -> int: + def parse(input: list[str]) -> list[Point]: + return [Point(*map(int, line.split(","))) for line in input] + + def compression_mapping(points: list[Point]) -> dict[Point, Point]: + def compress_1d(values: set[int]) -> dict[int, int]: + return {val: i for i, val in enumerate(sorted(values))} + + xs = compress_1d({p.x for p in points}) + ys = compress_1d({p.y for p in points}) + compress = lambda p: Point(xs[p.x], ys[p.y]) + + return {p: compress(p) for p in points} + + def line(p1: Point, p2: Point) -> Iterator[Point]: + def inclusive_range_any_order(a: int, b: int) -> Iterator[int]: + if a < b: + yield from range(a, b + 1) + else: + yield from range(a, b - 1, -1) + + # Hack-ish work-around to avoid infinite loops + if p1 == p2: + yield p1 + return + + xs = inclusive_range_any_order(p1.x, p2.x) + ys = inclusive_range_any_order(p1.y, p2.y) + + if p1.x == p2.x: + xs = itertools.repeat(p1.x) + + if p1.y == p2.y: + ys = itertools.repeat(p1.y) + + yield from map(Point._make, zip(xs, ys)) + + def draw_edges(tiles: list[Point]) -> set[Point]: + # Close the loop by repeating the first vertex at the end + vertices = tiles + [tiles[0]] + edges = {p for a, b in itertools.pairwise(vertices) for p in line(a, b)} + return edges + + def flood_fill(start: Point, points: set[Point]) -> set[Point]: + assert start in points # Sanity check + visited: set[Point] = set() + stack = [start] + while stack: + p = stack.pop() + visited.add(p) + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + n = Point(p.x + dx, p.y + dy) + if n in visited: + continue + if n not in points: + continue + stack.append(n) + return visited + + def fill_tiles(tiles: list[Point]) -> set[Point]: + # I'm too lazy to find an interior point to flood-fill to the edges from, + # instead fill the exterior and invert the set + min_x, max_x = min(p.x for p in tiles), max(p.x for p in tiles) + min_y, max_y = min(p.y for p in tiles), max(p.y for p in tiles) + + # Keep a border all around to make sure the flood-fill can reach everywhere + all_points = { + Point(x, y) + for x in range(min_x - 1, max_x + 1 + 1) + for y in range(min_y - 1, max_y + 1 + 1) + } + + edges = draw_edges(tiles) + + # Pick a corner we know for sure won't be in the polygon + start = Point(min_x - 1, min_y - 1) + + # Sever the points inside and outside the polygon, then flood-fill exterior + exterior = flood_fill(start, all_points - edges) + + # Return interior/edge points by removing everything that is on the exterior + return all_points - exterior + + def rectangle_edges(p: Point, other: Point) -> Iterator[Point]: + min_x, max_x = min(p.x, other.x), max(p.x, other.x) + min_y, max_y = min(p.y, other.y), max(p.y, other.y) + + c1 = Point(min_x, min_y) + c2 = Point(max_x, min_y) + c3 = Point(max_x, max_y) + c4 = Point(min_x, max_y) + + yield from line(c1, c2) + yield from line(c2, c3) + yield from line(c3, c4) + yield from line(c4, c1) + + def rectangle_area(p: Point, other: Point) -> int: + dx = abs(p.x - other.x) + dy = abs(p.y - other.y) + return (dx + 1) * (dy + 1) + + def inscribed_rectangles(tiles: list[Point]) -> Iterator[tuple[Point, Point]]: + inside_tiles = fill_tiles(tiles) + yield from ( + (a, b) + for a, b in itertools.combinations(tiles, 2) + if all(p in inside_tiles for p in rectangle_edges(a, b)) + ) + + def largest_rectangle_area(tiles: list[Point]) -> int: + to_compressed = compression_mapping(tiles) + decompress = {v: k for k, v in to_compressed.items()}.__getitem__ + compressed_tiles = [to_compressed[p] for p in tiles] + compressed_rectangles = inscribed_rectangles(compressed_tiles) + return max( + rectangle_area(decompress(a), decompress(b)) + for a, b in compressed_rectangles + ) + + tiles = parse(input) + return largest_rectangle_area(tiles) + + +def main() -> None: + input = sys.stdin.read().splitlines() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2025/d09/ex2/input b/2025/d09/ex2/input new file mode 100644 index 0000000..23578e0 --- /dev/null +++ b/2025/d09/ex2/input @@ -0,0 +1,496 @@ +97918,50201 +97918,51425 +98247,51425 +98247,52647 +98195,52647 +98195,53859 +98005,53859 +98005,55071 +97872,55071 +97872,56297 +97835,56297 +97835,57522 +97759,57522 +97759,58659 +97171,58659 +97171,59849 +96924,59849 +96924,61075 +96832,61075 +96832,62278 +96613,62278 +96613,63385 +96045,63385 +96045,64538 +95663,64538 +95663,65837 +95705,65837 +95705,66999 +95314,66999 +95314,68121 +94816,68121 +94816,69159 +94132,69159 +94132,70235 +93557,70235 +93557,71392 +93150,71392 +93150,72594 +92813,72594 +92813,73464 +91858,73464 +91858,74283 +90857,74283 +90857,75827 +91050,75827 +91050,76622 +90026,76622 +90026,77623 +89334,77623 +89334,78461 +88419,78461 +88419,79592 +87898,79592 +87898,80529 +87121,80529 +87121,81258 +86103,81258 +86103,82506 +85676,82506 +85676,82951 +84373,82951 +84373,84417 +84129,84417 +84129,84738 +82744,84738 +82744,85431 +81740,85431 +81740,86272 +80874,86272 +80874,86984 +79898,86984 +79898,87707 +78934,87707 +78934,88651 +78132,88651 +78132,89825 +77471,89825 +77471,90048 +76152,90048 +76152,91026 +75332,91026 +75332,91113 +73969,91113 +73969,92433 +73319,92433 +73319,92653 +72052,92653 +72052,92817 +70779,92817 +70779,93561 +69793,93561 +69793,94429 +68844,94429 +68844,94816 +67683,94816 +67683,94825 +66387,94825 +66387,95504 +65340,95504 +65340,96215 +64286,96215 +64286,95778 +62890,95778 +62890,96609 +61858,96609 +61858,97235 +60751,97235 +60751,97506 +59554,97506 +59554,97496 +58306,97496 +58306,97162 +57021,97162 +57021,97638 +55863,97638 +55863,98017 +54678,98017 +54678,98087 +53458,98087 +53458,98404 +52250,98404 +52250,98467 +51023,98467 +51023,97591 +49799,97591 +49799,97549 +48594,97549 +48594,97447 +47393,97447 +47393,97559 +46176,97559 +46176,97590 +44957,97590 +44957,97139 +43794,97139 +43794,97718 +42484,97718 +42484,97235 +41328,97235 +41328,97025 +40129,97025 +40129,96569 +38986,96569 +38986,96439 +37767,96439 +37767,96227 +36561,96227 +36561,95775 +35425,95775 +35425,95708 +34160,95708 +34160,94873 +33165,94873 +33165,94442 +32030,94442 +32030,93853 +30961,93853 +30961,93475 +29801,93475 +29801,93145 +28610,93145 +28610,92571 +27533,92571 +27533,91778 +26580,91778 +26580,91054 +25599,91054 +25599,90700 +24392,90700 +24392,90098 +23330,90098 +23330,89610 +22181,89610 +22181,88575 +21422,88575 +21422,87836 +20456,87836 +20456,87257 +19358,87257 +19358,86584 +18325,86584 +18325,85761 +17416,85761 +17416,84396 +17026,84396 +17026,83497 +16219,83497 +16219,82724 +15282,82724 +15282,81812 +14488,81812 +14488,81287 +13242,81287 +13242,80044 +12835,80044 +12835,79273 +11850,79273 +11850,78300 +11117,78300 +11117,77140 +10654,77140 +10654,76100 +10032,76100 +10032,75292 +9038,75292 +9038,74404 +8140,74404 +8140,73087 +7988,73087 +7988,71995 +7455,71995 +7455,71036 +6653,71036 +6653,69869 +6271,69869 +6271,68669 +5984,68669 +5984,67752 +5008,67752 +5008,66446 +5011,66446 +5011,65435 +4213,65435 +4213,64209 +4035,64209 +4035,63114 +3426,63114 +3426,61827 +3512,61827 +3512,60715 +2925,60715 +2925,59521 +2657,59521 +2657,58341 +2305,58341 +2305,57063 +2555,57063 +2555,55868 +2321,55868 +2321,54631 +2469,54631 +2469,53453 +1978,53453 +1978,52239 +1840,52239 +1840,51023 +1568,51023 +1568,50187 +94581,50187 +94581,48595 +2489,48595 +2489,47360 +1948,47360 +1948,46149 +2099,46149 +2099,44932 +2173,44932 +2173,43745 +2490,43745 +2490,42544 +2663,42544 +2663,41373 +3007,41373 +3007,40066 +2674,40066 +2674,39008 +3523,39008 +3523,37778 +3604,37778 +3604,36502 +3567,36502 +3567,35540 +4584,35540 +4584,34126 +4191,34126 +4191,33194 +5204,33194 +5204,32063 +5639,32063 +5639,30930 +6073,30930 +6073,29848 +6623,29848 +6623,28717 +7070,28717 +7070,27492 +7350,27492 +7350,26613 +8281,26613 +8281,25390 +8594,25390 +8594,24514 +9492,24514 +9492,23522 +10191,23522 +10191,22173 +10377,22173 +10377,21180 +11097,21180 +11097,20343 +12018,20343 +12018,19523 +12942,19523 +12942,18816 +13983,18816 +13983,17981 +14858,17981 +14858,16809 +15376,16809 +15376,16068 +16353,16068 +16353,15030 +17038,15030 +17038,14301 +18019,14301 +18019,13410 +18855,13410 +18855,12559 +19733,12559 +19733,12152 +20957,12152 +20957,10852 +21506,10852 +21506,10788 +22952,10788 +22952,9988 +23871,9988 +23871,8781 +24548,8781 +24548,8442 +25771,8442 +25771,7748 +26780,7748 +26780,7638 +28098,7638 +28098,6597 +28936,6597 +28936,6634 +30295,6634 +30295,5530 +31137,5530 +31137,5119 +32291,5119 +32291,5171 +33611,5171 +33611,4750 +34745,4750 +34745,4394 +35901,4394 +35901,4192 +37101,4192 +37101,3248 +38105,3248 +38105,3209 +39349,3209 +39349,2909 +40529,2909 +40529,2965 +41774,2965 +41774,2208 +42884,2208 +42884,2578 +44163,2578 +44163,2700 +45391,2700 +45391,1938 +46543,1938 +46543,2387 +47786,2387 +47786,2473 +48995,2473 +48995,2002 +50202,2002 +50202,1582 +51430,1582 +51430,1775 +52649,1775 +52649,2210 +53841,2210 +53841,2166 +55067,2166 +55067,2369 +56270,2369 +56270,2715 +57447,2715 +57447,2376 +58742,2376 +58742,3117 +59840,3117 +59840,2894 +61140,2894 +61140,3742 +62185,3742 +62185,3817 +63425,3817 +63425,3989 +64648,3989 +64648,5057 +65573,5057 +65573,4922 +66910,4922 +66910,5185 +68120,5185 +68120,5964 +69117,5964 +69117,6674 +70128,6674 +70128,6710 +71460,6710 +71460,7450 +72454,7450 +72454,8385 +73327,8385 +73327,8392 +74729,8392 +74729,9508 +75475,9508 +75475,10041 +76576,10041 +76576,10869 +77480,10869 +77480,11720 +78357,11720 +78357,12429 +79335,12429 +79335,12852 +80550,12852 +80550,13833 +81313,13833 +81313,14720 +82144,14720 +82144,15684 +82895,15684 +82895,16530 +83752,16530 +83752,17162 +84838,17162 +84838,17952 +85773,17952 +85773,18787 +86668,18787 +86668,19898 +87235,19898 +87235,20534 +88399,20534 +88399,21819 +88718,21819 +88718,22937 +89233,22937 +89233,23968 +89861,23968 +89861,24660 +91036,24660 +91036,25849 +91424,25849 +91424,26916 +92004,26916 +92004,27802 +92933,27802 +92933,28832 +93616,28832 +93616,30336 +93275,30336 +93275,31169 +94394,31169 +94394,32316 +94816,32316 +94816,33403 +95397,33403 +95397,34581 +95737,34581 +95737,35916 +95557,35916 +95557,37120 +95737,37120 +95737,38230 +96258,38230 +96258,39290 +97047,39290 +97047,40627 +96600,40627 +96600,41738 +97237,41738 +97237,42902 +97667,42902 +97667,44190 +97201,44190 +97201,45331 +97913,45331 +97913,46539 +98110,46539 +98110,47754 +98296,47754 +98296,48987 +97943,48987 +97943,50201