From 1944a69b5470f9fcc3a842c7d7cf8434831bb4de Mon Sep 17 00:00:00 2001 From: danmeo Date: Mon, 8 Dec 2025 23:06:04 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89D4P2=20Complete!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aoc_25/solutions/day04.py | 102 +++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 23 deletions(-) diff --git a/aoc_25/solutions/day04.py b/aoc_25/solutions/day04.py index 7386836..a742ff4 100644 --- a/aoc_25/solutions/day04.py +++ b/aoc_25/solutions/day04.py @@ -4,6 +4,7 @@ from utils.aoc_utils import report_results, AoCResult, input_for_day LooRollGrid = list[list[str]] +RollCoord = tuple[int, int] ORIGINAL_EXAMPLE: str = """..@@.@@@@. @@@.@.@.@@ @@ -21,30 +22,22 @@ DATA: LooRollGrid = [list(x) for x in INPUT_DATA] -def parse_loogrid_p1(data: LooRollGrid) -> int: - """Navigate through the Loo Roll Grid for AOCD4P1. - - Insert an extra layer of blank padding, slide a - 3x3 window and count adjacent loo rolls. - If less than 4 adjacent loo rolls, count it! +def forklift(data: LooRollGrid) -> list[RollCoord]: + """Forklift operations. Go through grid, find '@', + get window and check adjacent '@'. + If valid - add to list of valid coordinates. Args: - data (LooRollGrid): List of lists, @ = loo roll. + data (LooRollGrid): Puzzle input as a list of lists. Returns: - int: Count of valid positions. + list[RollCoord]: list of valid coordinates. """ - forklift_access: int = 0 - # add an extra padding 0 and -1 - for row in data: - row.insert(0, ".") - row.insert(len(data[0]), ".") - - # add an extra layer of padding... - data.insert(0, list("." * len(data[0]))) - data.insert(len(data), list("." * len(data[0]))) - # trundle through the grid + coords: list[RollCoord] = [] + row_idx: int + col_idx: int + for row_idx, row in enumerate(data[1:-1], 1): # print(ri, row[1:-1]) for col_idx, col in enumerate(row[1:-1], 1): @@ -59,18 +52,81 @@ def parse_loogrid_p1(data: LooRollGrid) -> int: # deduct the initial @ num_rolls: int = join_window.count("@") - 1 if num_rolls < 4: - forklift_access += 1 - return forklift_access + coords.append((row_idx, col_idx)) + + return coords + + +def pad_data(data: LooRollGrid) -> LooRollGrid: + """Pad initial grid with blanks. + + Args: + data (LooRollGrid): Puzzle input grid. + + Returns: + LooRollGrid: Padded puzzle grid. + """ + # add an extra padding 0 and -1 + padded_data: LooRollGrid = data.copy() + for row in padded_data: + row.insert(0, ".") + row.insert(len(data[0]), ".") + + # add an extra layer of padding... + padded_data.insert(0, list("." * len(padded_data[0]))) + padded_data.insert(len(padded_data), list("." * len(padded_data[0]))) + + return padded_data + + +def solve_p1(data: LooRollGrid) -> int: + """Solve P1. Iterate once - find valid coords. + + Args: + data (LooRollGrid): Puzzle input. + + Returns: + int: Number of valid loo roll coords. + """ + padded_data = pad_data(data) + valid_rolls = forklift(padded_data) + return len(valid_rolls) + + +def solve_p2(data: LooRollGrid) -> int: + """Recursively search for valid coords, + add to coordinate list. Replace those coords with 'x', + then repeat until no more can be replaced. + + Args: + data (LooRollGrid): Puzzle input. + + Returns: + int: Total valid loo roll removals. + """ + padded_data: LooRollGrid = pad_data(data) + total_removed: int = 0 + + while True: + coords: list[RollCoord] = forklift(padded_data) + if not coords: + break + + for x in coords: + padded_data[x[0]][x[1]] = 'x' + total_removed += len(coords) + + return total_removed @report_results def solveday(data: Any) -> AoCResult: - p1: int = parse_loogrid_p1(data) - p2: int = 0 + p1: int = solve_p1([row.copy() for row in data]) + p2: int = solve_p2([row.copy() for row in data]) return p1, p2 -expected_test_results: AoCResult = (13, 0) +expected_test_results: AoCResult = (13, 43) def tests(test_input: Any) -> None: