diff --git a/2024/d10/ex1/ex1.py b/2024/d10/ex1/ex1.py new file mode 100755 index 0000000..2d1a15f --- /dev/null +++ b/2024/d10/ex1/ex1.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import sys +from collections.abc import Iterator +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + def neighbours(self) -> Iterator["Point"]: + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + yield Point(self.x + dx, self.y + dy) + + +TopoMap = dict[Point, int] + + +def solve(input: str) -> int: + def parse(input: list[str]) -> TopoMap: + return { + Point(x, y): int(c) + for x, line in enumerate(input) + for y, c in enumerate(line) + } + + def find_trail_heads(map: TopoMap) -> set[Point]: + return {p for p, height in map.items() if height == 0} + + def score_trail(map: TopoMap, start: Point) -> int: + assert map[start] == 0 # Sanity check + res = 0 + queue = {start} + visited: set[Point] = set() + while queue: + p = queue.pop() + visited.add(p) + cur_height = map[p] + if cur_height == 9: + res += 1 + for n in p.neighbours(): + if map.get(n, cur_height) != (cur_height + 1): + continue + if n in visited: + continue + queue.add(n) + return res + + map = parse(input.splitlines()) + trail_heads = find_trail_heads(map) + return sum(score_trail(map, head) for head in sorted(trail_heads)) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2024/d10/ex1/input b/2024/d10/ex1/input new file mode 100644 index 0000000..462c756 --- /dev/null +++ b/2024/d10/ex1/input @@ -0,0 +1,59 @@ +18776569014346783430321009012345676543089876765012101843210 +09683458723454894321234218987432189452176769854323678956521 +14592987654098765436549367016543032360145678765014545697434 +23601678432132650145678456323456501278234549343478034788910 +10712569549241043278901285434787654329103234256589121078923 +89803434678950012789854398103490769210567145187678438967434 +67810326589867821016760187312521898123498076094501567456556 +50981810410778932345123272210634567087654189143215678304567 +41832900325696543451074561028701256198563778012324569213498 +32963871234587123898785654139987341017652890123473478012323 +87874562187671034567698763245676892456701287634982101701414 +96565653094544343452188898743786743326898096545679876894505 +05454512123349852143089889652898653217652125621043965787676 +12343103098256765001234767601701062108943034432152014690189 +01289544567187678114345678015612341007765403569061023543287 +01276632101096789823210599126543652210812312678278710871296 +10345789780125679814676587439874743321907654589189658960345 +01234695690434578705689436510165894430418523971012347454434 +12304504541128963210790325565256766569349010810143232323521 +23413213232037654309821019874305412678256186743256101210650 +34329832198747012313412301878912301569107898653087082198761 +65896701007658965412301498965887432354518947894198898017321 +96785432216234878905432567054896345823101456763234745654450 +87123870125165687876541230123445458910112398654125656723765 +21012965634018796982650345678032567421012567432098749810894 +76321034676569805401721214789121076578323456501589038902923 +85432123589458012392895603210434789489210167895610121451012 +96524323428301123483486578765965672374331321234785430543212 +87012410210216782174987439834874301065145490121096789678101 +73453891346785493065234328703893216521036787654567645679201 +02567765445698304160145012012743227434321098943658938983210 +11098894332103215659876430125652108965670101812340127654321 +25437743210114106765454309836543345696987872701235672105898 +36727654012325699877869218747434210780745963890104383236785 +49818123963445788566978745658923312321894854761201294345656 +56709037874236567345432036547012103456783203454398761787654 +43237654365187665432301127015432176501654112341432650198323 +54108910210094572301432098326721085432456043210541043278910 +45678921109001481676501287445856794101387456101650169867610 +38787632278112390789043016532943893232297887232789856701521 +29698543465243654632132105621032124540196996243456765432430 +10101012354305783541245094765021043256785432123455965432107 +67652765410216792150956783876107650122312301098767874345698 +58543894324345891067810782987238987201406784567854901236787 +49987685456543282123425691096543271230545493201993210340123 +32106452567650112054534567899454100045654320192387651259654 +40045321898342106567651056928767652198743410887434540568798 +51235430210289287438122345210178943329652378976543039875687 +67896787320176396129034434356598712410701237010132128064516 +10765698451965445001545423347895606549890796521243989123105 +23896787567843234652436710212874307432037887430145478798234 +34785896765432128763429876108963218901126986543234567017345 +25634789854578019854210785654851019985435100125676454156236 +18721034563689108943218798743344328776434234234981043205145 +09343123872672397654309654312235899643421965547872124314076 +43216012901521087898701211201156732554310876958943235023489 +56905438765432076985654300321076541467215467867654332133012 +47876329034310145676701098730987210398706326321038949874323 +56981010123421234565892345645678901237987015432127654365434 diff --git a/2024/d10/ex2/ex2.py b/2024/d10/ex2/ex2.py new file mode 100755 index 0000000..4297e62 --- /dev/null +++ b/2024/d10/ex2/ex2.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +import sys +from collections.abc import Iterator +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + def neighbours(self) -> Iterator["Point"]: + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + yield Point(self.x + dx, self.y + dy) + + +TopoMap = dict[Point, int] + + +def solve(input: str) -> int: + def parse(input: list[str]) -> TopoMap: + return { + Point(x, y): int(c) + for x, line in enumerate(input) + for y, c in enumerate(line) + } + + def find_trail_heads(map: TopoMap) -> set[Point]: + return {p for p, height in map.items() if height == 0} + + def rate_trail(map: TopoMap, start: Point) -> int: + def helper(pos: Point) -> int: + if map[pos] == 9: + return 1 + res = 0 + for n in pos.neighbours(): + if map.get(n, -1) != (map[pos] + 1): + continue + res += helper(n) + return res + + assert map[start] == 0 # Sanity check + return helper(start) + + map = parse(input.splitlines()) + trail_heads = find_trail_heads(map) + return sum(rate_trail(map, head) for head in sorted(trail_heads)) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2024/d10/ex2/input b/2024/d10/ex2/input new file mode 100644 index 0000000..462c756 --- /dev/null +++ b/2024/d10/ex2/input @@ -0,0 +1,59 @@ +18776569014346783430321009012345676543089876765012101843210 +09683458723454894321234218987432189452176769854323678956521 +14592987654098765436549367016543032360145678765014545697434 +23601678432132650145678456323456501278234549343478034788910 +10712569549241043278901285434787654329103234256589121078923 +89803434678950012789854398103490769210567145187678438967434 +67810326589867821016760187312521898123498076094501567456556 +50981810410778932345123272210634567087654189143215678304567 +41832900325696543451074561028701256198563778012324569213498 +32963871234587123898785654139987341017652890123473478012323 +87874562187671034567698763245676892456701287634982101701414 +96565653094544343452188898743786743326898096545679876894505 +05454512123349852143089889652898653217652125621043965787676 +12343103098256765001234767601701062108943034432152014690189 +01289544567187678114345678015612341007765403569061023543287 +01276632101096789823210599126543652210812312678278710871296 +10345789780125679814676587439874743321907654589189658960345 +01234695690434578705689436510165894430418523971012347454434 +12304504541128963210790325565256766569349010810143232323521 +23413213232037654309821019874305412678256186743256101210650 +34329832198747012313412301878912301569107898653087082198761 +65896701007658965412301498965887432354518947894198898017321 +96785432216234878905432567054896345823101456763234745654450 +87123870125165687876541230123445458910112398654125656723765 +21012965634018796982650345678032567421012567432098749810894 +76321034676569805401721214789121076578323456501589038902923 +85432123589458012392895603210434789489210167895610121451012 +96524323428301123483486578765965672374331321234785430543212 +87012410210216782174987439834874301065145490121096789678101 +73453891346785493065234328703893216521036787654567645679201 +02567765445698304160145012012743227434321098943658938983210 +11098894332103215659876430125652108965670101812340127654321 +25437743210114106765454309836543345696987872701235672105898 +36727654012325699877869218747434210780745963890104383236785 +49818123963445788566978745658923312321894854761201294345656 +56709037874236567345432036547012103456783203454398761787654 +43237654365187665432301127015432176501654112341432650198323 +54108910210094572301432098326721085432456043210541043278910 +45678921109001481676501287445856794101387456101650169867610 +38787632278112390789043016532943893232297887232789856701521 +29698543465243654632132105621032124540196996243456765432430 +10101012354305783541245094765021043256785432123455965432107 +67652765410216792150956783876107650122312301098767874345698 +58543894324345891067810782987238987201406784567854901236787 +49987685456543282123425691096543271230545493201993210340123 +32106452567650112054534567899454100045654320192387651259654 +40045321898342106567651056928767652198743410887434540568798 +51235430210289287438122345210178943329652378976543039875687 +67896787320176396129034434356598712410701237010132128064516 +10765698451965445001545423347895606549890796521243989123105 +23896787567843234652436710212874307432037887430145478798234 +34785896765432128763429876108963218901126986543234567017345 +25634789854578019854210785654851019985435100125676454156236 +18721034563689108943218798743344328776434234234981043205145 +09343123872672397654309654312235899643421965547872124314076 +43216012901521087898701211201156732554310876958943235023489 +56905438765432076985654300321076541467215467867654332133012 +47876329034310145676701098730987210398706326321038949874323 +56981010123421234565892345645678901237987015432127654365434