Advent of Code 2024, Day 15

In part 2, I found it hard to get the recursion right. I also had a bug where I didn’t return a copy of the original lines, but a modified version (even in the unsuccessful case), and another bug where I had a : instead of an =, but the interpreter didn’t complain.

Part 1

import sys

def free_spot(field, i, j, di, dj):
    if field[i][j] == ".":
        return field, True
    elif field[i][j] == "#":
        return field, False
    elif field[i][j] == "O":
        field, success = free_spot(field, i+di, j+dj, di, dj)
        if success:
            field[i+di][j+dj] = "O"
            field[i][j] = "."
            return field, True
        else:
            return field, False

def move_bot(field, i, j, di, dj):
    if field[i+di][j+dj] == ".":
        return field, i+di, j+dj
    elif field[i+di][j+dj] == "#":
        return field, i, j
    elif field[i+di][j+dj] == "O":
        field, success = free_spot(field, i+di, j+dj, di, dj)
        if success:
            return field, i+di, j+dj
        else:
            return field, i, j

def count_boxes(field):
    s = 0
    for i, line in enumerate(field):
        for j, c in enumerate(line):
            if c != "O": continue
            s += 100*i + j
    return s

with open(sys.argv[1]) as f:
    lines = [line.strip() for line in f]
    x = lines.index("")
    field, arrows = lines[:x], lines[x:]
    field = [[c for c in line] for line in field]
    for i, line in enumerate(field):
        for j, c in enumerate(line):
            if c == "@":
                pi, pj = i, j
                field[i][j] = "."
    moves = []
    for line in arrows:
        for c in line:
            if c == "^": moves.append((-1, 0))
            elif c == "v": moves.append((+1, 0))
            elif c == "<": moves.append((0, -1))
            elif c == ">": moves.append((0, 1))

for di, dj in moves:
    field, pi, pj = move_bot(field, pi, pj, di, dj)
print(count_boxes(field))

Part 2

import sys

def free_spot(field, i, j, di, dj):
    if field[i][j] == ".":
        return field, True
    elif field[i][j] == "#":
        return field, False
    elif di == 0:
        field, success = free_spot(field, i+di, j+dj, di, dj)
        if success:
            field[i+di][j+dj] = field[i][j]
            field[i][j] = "."
            return field, True
        else:
            return field, False
    elif field[i][j] == "[":
        old_field = [line[:] for line in field]
        field, success = free_spot(field, i+di, j+dj, di, dj)
        if not success:
            return old_field, False
        field, success = free_spot(field, i+di, j+dj+1, di, dj)
        if not success:
            return old_field, False
        field[i+di][j+dj] = "["
        field[i+di][j+dj+1] = "]"
        field[i][j] = "."
        field[i][j+1] = "."
        return field, True
    elif field[i][j] == "]":
        return free_spot(field, i, j-1, di, dj)

def move_bot(field, i, j, di, dj):
    if field[i+di][j+dj] == ".":
        return field, i+di, j+dj
    elif field[i+di][j+dj] == "#":
        return field, i, j
    elif field[i+di][j+dj] in "[]":
        field, success = free_spot(field, i+di, j+dj, di, dj)
        if success:
            return field, i+di, j+dj
        else:
            return field, i, j

def count_boxes(field):
    s = 0
    for i, line in enumerate(field):
        for j, c in enumerate(line):
            if c != "[": continue
            s += 100*i + j
    return s

with open(sys.argv[1]) as f:
    lines = [line.strip() for line in f]
    x = lines.index("")
    field, arrows = lines[:x], lines[x:]
    field = [line.replace("#", "##") for line in field]
    field = [line.replace("O", "[]") for line in field]
    field = [line.replace(".", "..") for line in field]
    field = [line.replace("@", "@.") for line in field]
    field = [[c for c in line] for line in field]
    for i, line in enumerate(field):
        for j, c in enumerate(line):
            if c == "@":
                pi, pj = i, j
                field[i][j] = "."
    moves = []
    for line in arrows:
        for c in line:
            if c == "^": moves.append((-1, 0))
            elif c == "v": moves.append((+1, 0))
            elif c == "<": moves.append((0, -1))
            elif c == ">": moves.append((0, 1))

for di, dj in moves:
    field, pi, pj = move_bot(field, pi, pj, di, dj)
print(count_boxes(field))

2024-12-19

Proxy Information
Original URL
gemini://dkalak.de/aoc/15.gmi
Status Code
Success (20)
Meta
text/gemini; lang=en
Capsule Response Time
108.03325 milliseconds
Gemini-to-HTML Time
0.305056 milliseconds

This content has been proxied by September (ba2dc).