利用DeepSeek辅助Python求解Advent of Code 2024第12题 篱笆墙

编程达人挑战赛·第5期 10w+人浏览 373人参与

原题地址

原文太长,我精简了一下。如下所示:
有一个方形花园,里面种了植物,用不同字母表示不同种类植物,把相邻的同类植物用篱笆围起来,与不同类的其他植物隔开。
比如:

AAAA
BBCD
BBCC
EEEC

可以分成5个区域,计算每个区域的图形的周长和面积。最后加总每个区域的周长乘面积

区域1:周长10,面积4
+-+-+-+-+
|A A A A|
+-+-+-+-+ 
区域2:周长4,面积1
+-+
|D|
+-+
区域3:周长8,面积4
+-+-+ 
|B B|  
+   +  
|B B|   
+-+-+  
区域4:周长8,面积3         
+-+-+-+ 
|E E E|
+-+-+-+
区域5:周长10,面积4 
+-+ 
|C|  
+ +-+
|C C|
+-+ +
  |C|
  +-+

以上图形的周长乘面积加总结果= 140。
如果区域完全包含另一个区域,周长要算内外的和,比如,如下图形O的区域周长=外圈(5x5方格)周长+内圈4个挖孔(每个1x1方格)的周长=20+4*4=36。

OOOOO
OXOXO
OOOOO
OXOXO
OOOOO

先用“遍历每个格子,如果紧挨的右侧是不同字符,就插入|,如果正下方挨着是不同字符就插入-,最后对|和-计数的方法”求周长,注意整个大方形外框也有-和|,用python实现。

我把上面的描述丢给deepseek,他一次做对,而且超过我的需求,不是先求周长,而是一次性做了全套,一定是学过。
计算第二问,我偷了个懒,直接丢给他原文,让他翻译并做题,完全不对,后来用下面一句话提示修改

计算边数的方法有误,同一行不间断的-算一个边,同一列不间断的|也算一个边。新的价格=面积乘以其边数,请修改,

他又一次做对了,感觉偶尔要抽风一下。这给我一个教训是,问DeepSeek的需求要简单明确,不要写太多废话。 提问时完全没提Advent of Code,仅凭描述就精准定位学过的知识也真是绝了。

第一问python程序,注意calculate_perimeter函数完全是应对我提出的方法,没有实际用途

def calculate_perimeter(grid):
    """
    计算网格中所有区域的周长
    使用算法:遍历每个格子,检查右边界和下边界
    """
    if not grid:
        return 0
    
    rows = len(grid)
    cols = len(grid[0])
    
    # 创建边界标记网格(比原网格大一圈,用于标记边界)
    # horizontal: 标记水平边界(-)
    # vertical: 标记垂直边界(|)
    horizontal = [[0] * (cols + 1) for _ in range(rows + 1)]
    vertical = [[0] * (cols + 1) for _ in range(rows + 1)]
    
    # 标记內部边界
    for i in range(rows):
        for j in range(cols):
            # 检查右侧边界
            if j + 1 < cols and grid[i][j] != grid[i][j + 1]:
                vertical[i][j + 1] = 1
            # 检查下侧边界
            if i + 1 < rows and grid[i][j] != grid[i + 1][j]:
                horizontal[i + 1][j] = 1
    
    # 标记外部边界
    # 上边界
    for j in range(cols):
        horizontal[0][j] = 1
    # 下边界
    for j in range(cols):
        horizontal[rows][j] = 1
    # 左边界
    for i in range(rows):
        vertical[i][0] = 1
    # 右边界
    for i in range(rows):
        vertical[i][cols] = 1
    
    # 计算总周长
    perimeter = 0
    for i in range(rows + 1):
        for j in range(cols + 1):
            perimeter += horizontal[i][j] + vertical[i][j]
    
    return perimeter

def calculate_region_perimeter_and_area(grid):
    """
    计算每个区域的周长和面积,并返回每个区域的(周长,面积)列表
    """
    if not grid:
        return []
    
    rows = len(grid)
    cols = len(grid[0])
    
    # 记录已访问的格子
    visited = [[False] * cols for _ in range(rows)]
    regions = []
    
    # 方向:上、右、下、左
    directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
    
    def bfs(start_i, start_j, plant_type):
        """使用BFS遍历一个区域"""
        queue = [(start_i, start_j)]
        visited[start_i][start_j] = True
        area = 0
        perimeter = 0
        
        while queue:
            i, j = queue.pop(0)
            area += 1
            
            # 检查四个方向的边界
            for di, dj in directions:
                ni, nj = i + di, j + dj
                
                # 如果邻居在网格内且类型相同
                if 0 <= ni < rows and 0 <= nj < cols and grid[ni][nj] == plant_type:
                    if not visited[ni][nj]:
                        visited[ni][nj] = True
                        queue.append((ni, nj))
                else:
                    # 遇到边界,周长+1
                    perimeter += 1
        
        return area, perimeter
    
    # 遍历所有格子,寻找未访问的区域
    for i in range(rows):
        for j in range(cols):
            if not visited[i][j]:
                plant_type = grid[i][j]
                area, perimeter = bfs(i, j, plant_type)
                regions.append((perimeter, area, plant_type))
    
    return regions

def calculate_total_perimeter_area_product(grid):
    """
    计算所有区域的(周长 × 面积)的总和
    """
    regions = calculate_region_perimeter_and_area(grid)
    total = 0
    #print("各区域统计:")
    for idx, (perimeter, area, plant_type) in enumerate(regions, 1):
        product = perimeter * area
        total += product
        #print(f"区域{idx}({plant_type}):周长{perimeter},面积{area},周长×面积={product}")
    print(f"总和:{total}")
    return total


filename = "2412-input0.txt"  # 你的文本文件名
#grid = read_grid_from_file(filename)

# 或者直接读取(不使用函数)
with open(filename, 'r', encoding='utf-8') as f:
    grid = [list(line.strip()) for line in f if line.strip()]

total = calculate_total_perimeter_area_product(grid)
print(total)

第二问python程序

def calculate_sides_for_region(grid, region_cells):
    """计算区域的边数"""
    if not region_cells:
        return 0
    
    rows = len(grid)
    cols = len(grid[0])
    plant_type = grid[next(iter(region_cells))[0]][next(iter(region_cells))[1]]
    
    # 边分为水平边和垂直边
    # 水平边:检查每个单元格的上方和下方
    # 垂直边:检查每个单元格的左方和右方
    
    # 记录所有的边
    horizontal_edges = set()  # 存储水平边:(row, col_start, col_end, 'top'/'bottom')
    vertical_edges = set()    # 存储垂直边:(col, row_start, row_end, 'left'/'right')
    
    # 检查每个单元格的边界
    for i, j in region_cells:
        # 检查上方是否是边界
        if i == 0 or (i-1, j) not in region_cells:
            # 这是一个水平边(上边)
            # 我们需要合并连续的边
            horizontal_edges.add((i, j, j, 'top'))
        
        # 检查下方是否是边界
        if i == rows-1 or (i+1, j) not in region_cells:
            # 这是一个水平边(下边)
            horizontal_edges.add((i+1, j, j, 'bottom'))
        
        # 检查左方是否是边界
        if j == 0 or (i, j-1) not in region_cells:
            # 这是一个垂直边(左边)
            vertical_edges.add((j, i, i, 'left'))
        
        # 检查右方是否是边界
        if j == cols-1 or (i, j+1) not in region_cells:
            # 这是一个垂直边(右边)
            vertical_edges.add((j+1, i, i, 'right'))
    
    # 合并水平边:同一行、同一边类型(top/bottom)、相邻的列
    merged_horizontal = set()
    sorted_horizontal = sorted(horizontal_edges, key=lambda x: (x[0], x[3], x[1]))
    
    current_edge = None
    for edge in sorted_horizontal:
        row, col_start, col_end, edge_type = edge
        if current_edge is None:
            current_edge = (row, col_start, col_end, edge_type)
        else:
            cr, cs, ce, ct = current_edge
            if cr == row and ct == edge_type and cs <= col_end <= ce + 1:
                # 可以合并
                current_edge = (cr, cs, max(ce, col_end), ct)
            else:
                merged_horizontal.add(current_edge)
                current_edge = (row, col_start, col_end, edge_type)
    
    if current_edge is not None:
        merged_horizontal.add(current_edge)
    
    # 合并垂直边:同一列、同一边类型(left/right)、相邻的行
    merged_vertical = set()
    sorted_vertical = sorted(vertical_edges, key=lambda x: (x[0], x[3], x[1]))
    
    current_edge = None
    for edge in sorted_vertical:
        col, row_start, row_end, edge_type = edge
        if current_edge is None:
            current_edge = (col, row_start, row_end, edge_type)
        else:
            cc, rs, re, ct = current_edge
            if cc == col and ct == edge_type and rs <= row_end <= re + 1:
                # 可以合并
                current_edge = (cc, rs, max(re, row_end), ct)
            else:
                merged_vertical.add(current_edge)
                current_edge = (col, row_start, row_end, edge_type)
    
    if current_edge is not None:
        merged_vertical.add(current_edge)
    
    # 边数 = 水平边数 + 垂直边数
    return len(merged_horizontal) + len(merged_vertical)

def calculate_new_total_price(grid):
    """计算新的总价(面积 × 边数)"""
    if not grid:
        return 0
    
    rows = len(grid)
    cols = len(grid[0])
    visited = [[False] * cols for _ in range(rows)]
    total_price = 0
    
    # 方向:上、右、下、左
    directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
    
    def bfs(start_i, start_j, plant_type):
        """BFS遍历区域,返回区域所有单元格的集合"""
        queue = [(start_i, start_j)]
        visited[start_i][start_j] = True
        cells = set()
        
        while queue:
            i, j = queue.pop(0)
            cells.add((i, j))
            
            for di, dj in directions:
                ni, nj = i + di, j + dj
                if (0 <= ni < rows and 0 <= nj < cols and 
                    grid[ni][nj] == plant_type and not visited[ni][nj]):
                    visited[ni][nj] = True
                    queue.append((ni, nj))
        
        return cells
    
    for i in range(rows):
        for j in range(cols):
            if not visited[i][j]:
                plant_type = grid[i][j]
                region_cells = bfs(i, j, plant_type)
                area = len(region_cells)
                sides = calculate_sides_for_region(grid, region_cells)
                region_price = area * sides
                total_price += region_price
    
    return total_price



filename = "2412-input.txt"  # 你的文本文件名
#grid = read_grid_from_file(filename)

# 或者直接读取(不使用函数)
with open(filename, 'r', encoding='utf-8') as f:
    grid = [list(line.strip()) for line in f if line.strip()]

total = calculate_new_total_price(grid)
print(total)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值