Skip to content

Commit

Permalink
AoC 2024 day 10 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
loociano committed Dec 10, 2024
1 parent 33f362d commit d7ee48d
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 14 deletions.
54 changes: 41 additions & 13 deletions aoc2024/src/day10/python/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
# limitations under the License.
from typing import Sequence

type Pos = tuple[int, int]
type Pos = tuple[int, int] # (y,x)

_TRAILHEAD = 0
_SUMMIT = 9
_IS_GRADUAL_SLOPE = lambda level, next_level: next_level == level + 1
_IS_WITHIN_BOUNDS = lambda pos, width, height: 0 <= pos[0] < height and 0 <= pos[1] < width
_DIRECTIONS = ((-1, 0), (0, 1), (1, 0), (0, -1))


def _find_trailheads(topographic_map: Sequence[str]) -> tuple[Pos, ...]:
Expand All @@ -30,28 +32,54 @@ def _find_trailheads(topographic_map: Sequence[str]) -> tuple[Pos, ...]:
return tuple(trailhead_positions)


def _count_reachable_summits(topo_map: Sequence[str], curr_pos: Pos, visited: set[Pos], num_summits: list[int]):
def _count_summits(topo_map: Sequence[str], curr_pos: Pos, visited: set[Pos], counter: list[int]):
"""Counts the number of summits that can be reached from a position."""
curr_level = int(topo_map[curr_pos[0]][curr_pos[1]])
if curr_level == _SUMMIT and curr_pos not in visited:
num_summits[0] += 1
visited.add(curr_pos)
if curr_level == _SUMMIT:
if curr_pos not in visited:
counter[0] += 1
visited.add(curr_pos)
return
visited.add(curr_pos)
for step in ((-1, 0), (0, 1), (1, 0), (0, -1)):
for step in _DIRECTIONS:
next_pos = (curr_pos[0] + step[0]), (curr_pos[1] + step[1])
within_map = 0 <= next_pos[0] < len(topo_map) and 0 <= next_pos[1] < len(topo_map[0])
if next_pos not in visited and within_map:
if next_pos not in visited and _IS_WITHIN_BOUNDS(next_pos, len(topo_map[0]), len(topo_map)):
next_level = int(topo_map[next_pos[0]][next_pos[1]])
if _IS_GRADUAL_SLOPE(curr_level, next_level):
_count_reachable_summits(topo_map, next_pos, visited, num_summits)
_count_summits(topo_map, next_pos, visited, counter)


def _count_distinct_paths(topo_map: Sequence[str], curr_pos: Pos, counter: list[int]):
"""Counts the number of distinct paths from trailhead to summit."""
curr_level = int(topo_map[curr_pos[0]][curr_pos[1]])
if curr_level == _SUMMIT:
counter[0] += 1
return
for step in _DIRECTIONS:
next_pos = (curr_pos[0] + step[0]), (curr_pos[1] + step[1])
if _IS_WITHIN_BOUNDS(next_pos, len(topo_map[0]), len(topo_map)):
next_level = int(topo_map[next_pos[0]][next_pos[1]])
if _IS_GRADUAL_SLOPE(curr_level, next_level):
_count_distinct_paths(topo_map, next_pos, counter)


def get_score_sum(topographic_map: Sequence[str]) -> int:
"""Gets the sum of all the trails from all the trailheads."""
sum_scores = 0
score_sum = 0
trailheads_positions: tuple[Pos, ...] = _find_trailheads(topographic_map)
for trailhead_pos in trailheads_positions:
num_summits = [0] # Pass by reference.
_count_reachable_summits(topographic_map, trailhead_pos, set(), num_summits)
sum_scores += num_summits[0]
return sum_scores
_count_summits(topographic_map, trailhead_pos, set(), num_summits)
score_sum += num_summits[0]
return score_sum


def get_rating_sum(topographic_map: Sequence[str]) -> int:
"""Gets the sum of all distinct trails from all the trailheads."""
rating_sum = 0
trailheads_positions: tuple[Pos, ...] = _find_trailheads(topographic_map)
for trailhead_pos in trailheads_positions:
num_trails = [0] # Pass by reference.
_count_distinct_paths(topographic_map, trailhead_pos, num_trails)
rating_sum += num_trails[0]
return rating_sum
7 changes: 7 additions & 0 deletions aoc2024/test/day10/python/example5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1111801
1143211
1151121
1165431
1171141
1187651
1191111
7 changes: 7 additions & 0 deletions aoc2024/test/day10/python/example6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1190219
1111198
1112117
6543456
7651987
8761111
9871111
6 changes: 6 additions & 0 deletions aoc2024/test/day10/python/example7.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
012345
123456
234567
345678
416789
567891
8 changes: 8 additions & 0 deletions aoc2024/test/day10/python/example8.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732
17 changes: 16 additions & 1 deletion aoc2024/test/day10/python/test_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import unittest

from common.python3.AdventOfCodeTestCase import AdventOfCodeTestCase
from aoc2024.src.day10.python.solution import get_score_sum
from aoc2024.src.day10.python.solution import get_score_sum, get_rating_sum


class TestDay09Solution(AdventOfCodeTestCase):
Expand All @@ -36,6 +36,21 @@ def test_part1_withExample4_getsScore(self):
def test_part1_withPuzzleInput_getsScore(self):
self.assertEqual(825, get_score_sum(self.input))

def test_part2_withExample_getsRating(self):
self.assertEqual(3, get_rating_sum(self.examples[4]))

def test_part2_withExample2_getsRating(self):
self.assertEqual(13, get_rating_sum(self.examples[5]))

def test_part2_withExample3_getsRating(self):
self.assertEqual(227, get_rating_sum(self.examples[6]))

def test_part2_withExample4_getsRating(self):
self.assertEqual(81, get_rating_sum(self.examples[7]))

def test_part2_withPuzzleInput_getsRating(self):
self.assertEqual(1805, get_rating_sum(self.input))


if __name__ == '__main__':
unittest.main()

0 comments on commit d7ee48d

Please sign in to comment.