Callista Krebs

Home Projects Contact

Advent of Code - Day 10

< Prev Day Next Day >

Part 1

My Code

def hike(grid, starting_point, peaks = None):
    startr = starting_point[0]
    startc = starting_point[1]

    if peaks is None:
        peaks = set()
    for dr, dc in directions:
        newr, newc = startr + dr, startc + dc 
        if 0 <= newr <= len(grid) - 1 and 0 <= newc <= len(grid) - 1:
            if grid[newr][newc] == grid[startr][startc] + 1:
                if grid[newr][newc] == 9:
                    peaks.add((newr, newc))
                else:
                    hike(grid, (newr,newc), peaks)
    return peaks

directions = [
    (0, -1), # up
    (0, 1), # down
    (-1, 0), #left
    (1, 0) #right

]

if __name__ == "__main__":
    with open("day10.txt") as f:
        grid = f.read().split("\n")
        grid = [list(map(int,list(row))) for row in grid]
    
    nrows = len(grid)
    ncols = len(grid[0])

    scores = {}
    for r in range(nrows):
        for c in range(ncols):
            if grid[r][c] == 0:
                reachable_peaks = hike(grid, (r,c))
                scores[(r,c)] = len(reachable_peaks)

    print(sum(scores.values()))

ChatGPT’s Improved Code

def hike(grid, starting_point, peaks=None, visited=None):
    if peaks is None:
        peaks = set()
    if visited is None:
        visited = set()
    
    startr, startc = starting_point
    visited.add((startr, startc))
    
    for dr, dc in DIRECTIONS:
        newr, newc = startr + dr, startc + dc
        if 0 <= newr < len(grid) and 0 <= newc < len(grid[0]):
            if (newr, newc) not in visited and grid[newr][newc] == grid[startr][startc] + 1:
                if grid[newr][newc] == 9:
                    peaks.add((newr, newc))
                else:
                    hike(grid, (newr, newc), peaks, visited)
    return peaks

DIRECTIONS = [
    (0, -1),  # up
    (0, 1),   # down
    (-1, 0),  # left
    (1, 0)    # right
]

if __name__ == "__main__":
    with open("day10.txt") as f:
        grid = [list(map(int, list(row))) for row in f.read().strip().split("\n")]
    
    nrows = len(grid)
    ncols = len(grid[0])
    scores = {}

    for r in range(nrows):
        for c in range(ncols):
            if grid[r][c] == 0:
                reachable_peaks = hike(grid, (r, c))
                scores[(r, c)] = len(reachable_peaks)

    print(f"Total reachable peaks: {sum(scores.values())}")

Part 2

My Code

from collections import defaultdict

def hike(grid, starting_point, peaks = None, rating = None):
    startr = starting_point[0]
    startc = starting_point[1]

    if peaks is None:
        peaks = defaultdict(int)

    for dr, dc in directions:
        newr, newc = startr + dr, startc + dc 
        if 0 <= newr <= len(grid) - 1 and 0 <= newc <= len(grid) - 1:
            if grid[newr][newc] == grid[startr][startc] + 1:
                if grid[newr][newc] == 9:
                    peaks[(newr, newc)] += 1
                else:
                    hike(grid, (newr,newc), peaks)
    return peaks

directions = [
    (0, -1), # up
    (0, 1), # down
    (-1, 0), #left
    (1, 0) #right

]

if __name__ == "__main__":
    with open("day10.txt") as f:
        grid = f.read().split("\n")
        grid = [list(map(int,list(row))) for row in grid]
    
    nrows = len(grid)
    ncols = len(grid[0])

    rating = {}
    for r in range(nrows):
        for c in range(ncols):
            if grid[r][c] == 0:
                peaks_nroutes = hike(grid, (r,c))
                rating[(r,c)] = sum(peaks_nroutes.values())

    print(sum(rating.values()))

ChatGPT’s Improved Code

At first attempt, ChatGPT tried to use the visited set implementation in Part 2 as well, but I pointed out that this won’t work for Part 2, because we care about the number of distinct paths to reach the peaks (grid values of 9), and so we can’t disregard states just because they had already been visited.

from collections import defaultdict

def hike(grid, starting_point, peaks=None):
    if peaks is None:
        peaks = defaultdict(int)

    startr, startc = starting_point

    for dr, dc in DIRECTIONS:
        newr, newc = startr + dr, startc + dc
        if 0 <= newr < len(grid) and 0 <= newc < len(grid[0]):
            if grid[newr][newc] == grid[startr][startc] + 1:
                if grid[newr][newc] == 9:
                    peaks[(newr, newc)] += 1
                else:
                    # Recursively explore all paths
                    sub_peaks = hike(grid, (newr, newc))
                    for peak, count in sub_peaks.items():
                        peaks[peak] += count
    return peaks

DIRECTIONS = [
    (0, -1),  # up
    (0, 1),   # down
    (-1, 0),  # left
    (1, 0)    # right
]

if __name__ == "__main__":
    with open("day10.txt") as f:
        grid = [list(map(int, list(row))) for row in f.read().strip().split("\n")]

    nrows, ncols = len(grid), len(grid[0])

    ratings = {}
    for r in range(nrows):
        for c in range(ncols):
            if grid[r][c] == 0:
                peaks_nroutes = hike(grid, (r, c))
                ratings[(r, c)] = sum(peaks_nroutes.values())

    print(f"Total distinct routes to peaks: {sum(ratings.values())}")

What I Learned

Recursion with Collections

Memoization

Python Constant Naming Convention

Unpacking Tuples

Isolation of Recursive Calls


Callista Krebs, 2024