🎄Advent of Code 2025 挑战全手写代码 Day 4 - 印刷部门
大家好,今天咱们继续更新 Advent of Code 2025 的解题记录。
第四天题目 Printing Department,难度 ⭐(1 星),主要考察 矩阵和模拟(simulation)。
📖 题目速览
题目地址:adventofcode.com/2025/day/4
背景:
我们坐扶梯下到印刷部,为了打破一堵墙进入自助餐厅,我们需要指挥叉车搬运成堆的纸卷(用 @ 表示),这样闲下来的叉车就能帮我们打破墙壁了。
Part 1: 叉车的作业规则
题目给出一个由 . (空地) 和 @ (纸卷) 组成的网格。
叉车搬运纸卷有一个限制:只有当一个纸卷周围 8 个方向(上下左右及对角线)的纸卷数量少于 4 个时,叉车才能接触并搬走它。
Part 1 的问题很简单:当前状态下,有多少个纸卷可以被叉车叉走?
Part 2: 连锁反应
Part 2 引入了时间维度的模拟。 一旦一个纸卷被移除,它原来的位置就变成了空地。这可能会导致原本因为拥挤而无法被接触到的内部纸卷,在周围变空后,变得可以被接触到了。 这是一个重复的过程:
- 找出所有当前可以移除的纸卷。
- 移除它们。
- 重复步骤 1,直到没有任何纸卷可以被移除。
问题是:总共能移除多少个纸卷?
解题思路
数据结构
直接使用二维列表 list[list[str]] 来存储网格即可。内层使用list而不是一整条str是因为在 part 2 我们需要对网格进行写操作。
核心逻辑:检查邻居
无论是 Part 1 还是 Part 2,核心都是判断一个坐标 (x, y) 是否满足“周围 @ 数量 < 4”。
def _can_fork(self, idx: int, jdx: int) -> bool:
"""检查该位置的纸卷是否可以被叉车接触"""
adjacent_coordinates = (
(idx - 1, jdx - 1), (idx, jdx - 1), (idx + 1, jdx - 1),
(idx - 1, jdx), (idx + 1, jdx),
(idx - 1, jdx + 1), (idx, jdx + 1), (idx + 1, jdx + 1),
)
count = 0
for x, y in adjacent_coordinates:
# 边界检查
if 0 <= x < len(self.grid[0]) and 0 <= y < len(self.grid) and self.grid[y][x] == "@":
count += 1
return count < 4
Part 1 实现
直接遍历整个网格,对每个 @ 调用 _can_fork,计数即可。
Part 2 的踩坑与反思
❌ 错误的尝试:检查过程中的逻辑错误
一开始我为了图省事,写出了类似这样的逻辑:
# 错误示范
def _can_fork(self, idx: int, jdx: int) -> bool:
"""check if the cell can fork"""
adjacent_coordinates = ...
out: int = 0
for x, y in adjacent_coordinates:
if 0 <= x < len(self.grid[0]) and 0 <= y < len(self.grid):
if self.grid[y][x] == "@":
self.grid[y][x] = "." # <--- 问题出在这里!
out += 1
return out <= 3
为什么这是错的?
本来应该将符合条件的目标位置改为".",但忙中出错,反而将目标周围的@修改了,这导致每一轮中都有纸卷被错误地标记为“移除”,从而出现运行时的死循环。
✅ 正确的实现
正确的做法是只更改目标位置的纸卷:
def part2(self) -> int:
total: int = 0
while True:
single_round: int = 0
for jdx, row in enumerate(self.grid):
for idx, char in enumerate(row):
if char == ".":
continue
if self._can_fork(idx, jdx):
self.grid[jdx][idx] = "." # <- 就是这里
single_round += 1
if not single_round:
break
total += single_round
return total
总结
Day 4 本来难度不高,但因为一开始急于求解,反而造成了逻辑错误,我要反思(doge
完整代码:访问 github
Happy Coding,今天也要继续冲榜~