Day 4: Printing Department

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 4 points 7 months ago* (last edited 7 months ago)

Python

Simple brute-force is enough.

DIRECTIONS = [
    (0, 1), (1, 0), (0, -1), (-1, 0),   # cardinal
    (1, 1), (1, -1), (-1, 1), (-1, -1)  # diagonal
]
# yield all valid neighbor coordinates
def yield_neighbors(i, j, m, n):
    for di, dj in DIRECTIONS:
        ni, nj = i+di, j+dj
        if 0 <= ni < m and 0 <= nj < n:
            yield ni, nj

# build char grid from input data
def build_grid(data: str):
    return [list(row) for row in data.splitlines()]

def part1(data: str):
    grid = build_grid(data)
    m, n = len(grid), len(grid[0])

    # count accessible rolls
    accessible = 0
    for i in range(m):
        for j in range(n):
            if grid[i][j] != '@':
                continue

            neighbor_rolls = sum(grid[ni][nj] == '@' for ni, nj in yield_neighbors(i, j, m, n))
            if neighbor_rolls < 4:
                accessible += 1
    return accessible

def part2(data: str):
    grid = build_grid(data)
    m, n = len(grid), len(grid[0])

    total_accessible = 0    # total accessible rolls over all cycles
    accessible = None       # rolls accessible this cycle

    # repeat until no more rolls can be accessed
    while accessible != 0:
        accessible = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] != '@':
                    continue

                neighbor_rolls = sum(grid[ni][nj] == '@' for ni, nj in yield_neighbors(i, j, m, n))
                if neighbor_rolls < 4:
                    accessible += 1
                    # we can immediately remove this roll, no need to wait for next cycle
                    grid[i][j] = '.'
        
        # accumulate accessible rolls this cycle
        total_accessible += accessible
    return total_accessible

sample = """<paste sample here>"""
assert part1(sample) == 13
assert part2(sample) == 43
  • source