利用DeepSeek辅助PuLP求解Advent of Code 2025第10题 电子工厂 第2部分

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

原题地址

前面,DeepSeek用numpy的线性规划没有解答完成。听张泽鹏先生说他用PuLP这个库整数规划解决了。今天也让DeepSeek编一个。

请用PuLP这个库整数规划解决电压按钮问题,不做别的

他给出了如下程序

import re
import pulp

def parse_line_part2(line):
    """解析一行数据,返回电压要求和按钮列表(第二部分)"""
    # 匹配大括号部分
    match_brace = re.search(r'\{([^}]+)\}', line)
    if not match_brace:
        return None, None
    
    # 解析电压要求
    joltage_str = match_brace.group(1)
    target = [int(x.strip()) for x in joltage_str.split(',')]
    
    # 匹配所有圆括号部分
    buttons = []
    pattern = r'\(([^)]+)\)'
    matches = re.findall(pattern, line)
    
    for match in matches:
        # 解析圆括号内的数字
        nums = [int(x.strip()) for x in match.split(',')]
        buttons.append(nums)
    
    return target, buttons

def solve_machine_pulp(target, buttons):
    """使用PuLP整数规划求解单个机器的电压配置问题"""
    n_counters = len(target)
    n_buttons = len(buttons)
    
    # 创建整数规划问题
    prob = pulp.LpProblem("ButtonPresses", pulp.LpMinimize)
    
    # 创建决策变量(每个按钮的按压次数,非负整数)
    x = pulp.LpVariable.dicts('x', range(n_buttons), 
                              lowBound=0, cat='Integer')
    
    # 目标函数:最小化总按压次数
    prob += pulp.lpSum([x[i] for i in range(n_buttons)])
    
    # 约束条件:每个计数器的总增加量必须等于目标值
    for counter in range(n_counters):
        # 计算影响该计数器的所有按钮的总贡献
        total_effect = pulp.lpSum([
            x[btn_idx] for btn_idx in range(n_buttons) 
            if counter in buttons[btn_idx]
        ])
        prob += total_effect == target[counter], f"Counter_{counter}_Constraint"
    
    # 求解问题
    prob.solve(pulp.PULP_CBC_CMD(msg=False))
    
    # 检查求解状态
    if pulp.LpStatus[prob.status] == 'Optimal':
        # 提取解
        presses_list = [int(pulp.value(x[i])) for i in range(n_buttons)]
        total_presses = sum(presses_list)
        return total_presses, presses_list, "求解成功"
    elif pulp.LpStatus[prob.status] == 'Infeasible':
        return -1, None, "无可行解"
    else:
        return -1, None, f"求解失败: {pulp.LpStatus[prob.status]}"

def validate_solution(target, buttons, presses_list):
    """验证解是否正确"""
    if presses_list is None:
        return False, None
    
    m = len(target)
    current = [0] * m
    
    for j, press_count in enumerate(presses_list):
        if press_count > 0:
            for idx in buttons[j]:
                current[idx] += press_count
    
    return current == target, current

def main():
    total_presses = 0
    success_count = 0
    fail_count = 0
    
    # 读取输入文件
    with open('2510-input.txt', 'r') as f:
        lines = f.read().strip().splitlines()
    
    for i, line in enumerate(lines):
        target, buttons = parse_line_part2(line)
        if target is None or not buttons:
            continue
        
        min_presses, presses_list, message = solve_machine_pulp(target, buttons)
        
        if min_presses >= 0:
            # 验证解
            is_valid, calculated = validate_solution(target, buttons, presses_list)
            
            if is_valid:
                print(f"机器 {i+1}: {min_presses} 次按压 ({message})")
                print(f"  按钮按压次数: {presses_list}")
                print(f"  验证通过: {calculated} == {target}")
                total_presses += min_presses
                success_count += 1
            else:
                print(f"机器 {i+1}: 验证失败! ({message})")
                print(f"  尝试解: {presses_list}")
                print(f"  计算值: {calculated} != 目标值: {target}")
                fail_count += 1
        else:
            print(f"机器 {i+1}: 求解失败 ({message})")
            fail_count += 1
    
    print(f"\n总结:")
    print(f"成功求解: {success_count} 台机器")
    print(f"失败: {fail_count} 台机器")
    print(f"总最少按压次数: {total_presses}")
    return total_presses

if __name__ == "__main__":
    main()

安装pulp

python3 pip.pyz install pulp --break-system-packages -i https://pypi.tuna.tsinghua.edu.cn/simple

执行

time python3 2510pulp.txt >2510pulp-res.txt

real	0m0.783s
user	0m0.224s
sys	0m0.056s

cat 2510pulp-res.txt
...
机器 194: 69 次按压 (求解成功)
  按钮按压次数: [0, 16, 25, 25, 1, 2]
  验证通过: [41, 51, 41, 43] == [41, 51, 41, 43]
机器 195: 37 次按压 (求解成功)
  按钮按压次数: [20, 8, 9]
  验证通过: [29, 8, 37, 28, 37] == [29, 8, 37, 28, 37]

总结:
成功求解: 195 台机器
失败: 0 台机器

看来问DeepSeek问题不但要说清楚需求,还要说对工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值