利用DeepSeek辅助编写优化求解Advent of Code 2024第9题 磁盘碎片整理第一部分的python程序

原SQL解法是把区块展开的思路,现在让他沿用第二部分的不展开思路。

请用第二部分的思路(不实际展开块)编写第一部分的解答程序,注意如下区别。1.文件是逐个块移动到空闲块,紧密放置。2.最右一个文件的块多于当前最左空闲块时,顺序填充到最左空闲块右边的空闲块,以此类推。停止移动条件是最右文件块左边无空闲块,移动完成后右边一定是连续的空闲块

结果不对,应该是没处理好一个空闲区块填充多个文件的问题。
继续提示

程序计算结果偏小,修改填充思路为从左到右,先计算第一个文件块chksum,然后模拟逐个最右文件块填入空闲块,填充某空闲区块(标记的长度>0)的单个块即计算chksum,一个区块多长,就计算多少次,跳到下个空闲区块之前,先计算中间间隔的文件块chksum,直到没有文件块可读。数据结构可以统一为bs be,用下标的奇偶性判断文件还是空闲区块,算的过程不用修改已填充部分,只要用一个指针记录右侧消除掉的文件fid 最后位置,按此思路改写

这次结果偏大,经过调试,发现循环轮数过多。
继续提示

算得多了,增加一个停止条件,当前填充位置已经是当前文件左邻空闲区块,下一个文件不能回绕到区块左侧, 只给出增加这个的代码段,不做别的

终于对了。完成的代码如下:

# Standard Library
import pathlib


def get_input(filename: str) -> list[str]:
    """
    Takes a filename and returns a list of lines from the file
    """
    output = []
    file = pathlib.Path(filename)
    with open(file) as f:
        for line in f:
            tmp_line = line.strip()
            output.append(tmp_line)
    return output

def solve_part1():
    import sys
    data = get_input("2409-input.txt")[0] #sys.stdin.read().strip()

    # 1. 解析得到统一的 blocks 列表
    bs, be = [], []
    pos = 0
    is_file = True
    file_id = 0
    for ch in data:
        length = int(ch)
        bs.append(pos)
        be.append(pos + length - 1)
        pos += length
        is_file = not is_file

    n_blocks = len(bs)
    #print(bs,be)
    # 2. 准备文件ID映射:偶数下标是文件,分配文件ID
    file_ids = []
    fid = 0
    for i in range(n_blocks):
        if i % 2 == 0:  # 文件
            file_ids.append(fid)
            fid += 1
        else:  # 空闲区
            file_ids.append(-1)
    #print(file_ids)
    # 3. 模拟移动并计算校验和
    checksum = 0
    current_pos = 0  # 当前计算位置
    right_file_ptr = n_blocks - 1  # 指向最右的文件块(用于填充)
    
    # 找到初始最右的文件块(最后一个偶数下标)
    while right_file_ptr >= 0 and right_file_ptr % 2 != 0:
        right_file_ptr -= 1
    flag=0
    for i in range(n_blocks):
        start, end = bs[i], be[i]
        
        if i % 2 == 0:  # 文件块
            # 计算这个文件的所有块
            for pos in range(start, end + 1):
                checksum += pos * file_ids[i]
                #if i==2:print(pos,file_ids[i],"---")
            current_pos = end + 1
            
        else:  # 空闲区
            # 逐个填充这个空闲区的每个位置
            for pos in range(start, end + 1):
                # 检查是否还有文件块可填充
                while right_file_ptr >= 0:
                    right_start, right_end = bs[right_file_ptr], be[right_file_ptr]
                    if right_end >= right_start:  # 这个文件还有块
                        # 停止条件:当前填充位置已经是当前文件左邻空闲区块
                        if pos >= right_start:
                            # 下一个文件不能回绕到区块左侧,停止填充
                            flag=1;break 
                        # 填充最右块到当前位置
                        checksum += pos * file_ids[right_file_ptr]
                        # 消耗掉这个文件的最右块
                        be[right_file_ptr] -= 1
                        break
                    else:
                        # 这个文件用完了,找前一个文件
                        right_file_ptr -= 2
                        # 跳过空闲区,找文件
                        while right_file_ptr >= 0 and right_file_ptr % 2 != 0:
                            right_file_ptr -= 1
                else:
                    # 没有文件块可填充了,退出
                    break
                if flag==1:break
            current_pos = end + 1
        #print(checksum)    
        # 检查是否所有文件块都已用完
        if right_file_ptr < 0 or flag==1:
            break
    
    print(checksum)

if __name__ == "__main__":
    solve_part1()

SQL版本快了几倍

time python3 2409part1.py
6340197768906

real	0m0.087s
user	0m0.052s
sys	0m0.004s

time ./duckdb150 -c ".read 2409fastcode.txt"
┌─────────────────┐
│     chksum      │
│     int128      │
├─────────────────┤
│  6340197768906  │
│ (6.34 trillion) │
└─────────────────┘

real	0m0.877s
user	0m0.628s
sys	0m0.156s

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值