news 2026/4/24 22:50:08

利用DeepSeek辅助DuckDB SQL求解Advent of Code 2025第10题 电子工厂

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
利用DeepSeek辅助DuckDB SQL求解Advent of Code 2025第10题 电子工厂

前期嫌SQL处理麻烦和性能不足,用python做过一个,
最近看到clickhouse微信公众号文章用纯 SQL 硬刚 Advent of Code?ClickHouse 把「不可能」变成了 12 天的现实。
看到了希望,所以用DuckDB SQL重新做过。

第一部分格式转换代码如下,都是自己完成的:

withrecursive tas(select'[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}'t),bas(selectrow_number()over()rn,reverse(substr(b,2,instr(b,']')-2))b1,--信号灯字符串,格式.##.,注意要翻转字符串substr(b,instr(b,']')+2,instr(b,'{')-3-instr(b,']'))b2,--按钮字符串,格式(3) (1,3) (2) (2,3) (0,2) (0,1)substr(b,instr(b,'{')+1,instr(b,'}')-1-instr(b,'{'))b3,--伏特字符串,格式3,5,4,7translate(b1,'#.','10')::bit::intb1a,--转二进制位再转整数list_reduce([0]||string_split(unnest(string_split(replace(replace(b2,')',''),'(',''),' ')),',')::int[],lambda x,y :(x+(1<<y)))b2a,--按钮转成整数列表string_split(b3,',')::int[]b3a,from(selectunnest(string_split(t,chr(10)))bfromt)),das(selectrn,b1a,array_agg(b2a)a,b3afrombgroupbyall)fromdorderbyrn;

示例数据子查询d的结果如下

┌───────┬───────┬──────────────────────┬────────────────────────┐ │ rn │ b1a │ a │ b3a │ │ int64 │ int32 │ int32[] │ int32[] │ ├───────┼───────┼──────────────────────┼────────────────────────┤ │ 1 │ 6 │ [8, 10, 4, 12, 5, 3] │ [3, 5, 4, 7] │ │ 2 │ 8 │ [29, 12, 17, 7, 30] │ [7, 5, 12, 7, 2] │ │ 3 │ 46 │ [31, 25, 55, 6] │ [10, 11, 11, 5, 10, 5] │ └───────┴───────┴──────────────────────┴────────────────────────┘

一开始没注意信号灯字符串从左到右是从低位到高位,没做翻转,导致算错了b1a。

┌───────┬───────┬──────────────────────┬────────────────────────┐ │ rn │ b1a │ a │ b3a │ │ int64 │ int32 │ int32[] │ int32[] │ ├───────┼───────┼──────────────────────┼────────────────────────┤ │ 1 │ 6 │ [8, 10, 4, 12, 5, 3] │ [3, 5, 4, 7] │ │ 2 │ 2 │ [29, 12, 17, 7, 30] │ [7, 5, 12, 7, 2] │ │ 3 │ 29 │ [31, 25, 55, 6] │ [10, 11, 11, 5, 10, 5] │ └───────┴───────┴──────────────────────┴────────────────────────┘

DeepSeek辅助完成将每行按钮的各种组合求出。

我有一个数组a,包含n个元素,请用duckdb语法编写一句SQL,输出数组a的全部子集,比如[1,3]输出[],[1],[3],[1,3],

可以使用 DuckDB 的UNNEST配合WITH RECURSIVE递归生成子集。以下是 SQL 语句:

WITHRECURSIVE subsetsAS(-- 初始:空子集SELECT[]ASsubset,1ASlevelUNIONALL-- 递归:逐个添加元素SELECTarray_append(subset,a.val)ASsubset,level+1ASlevelFROMsubsets,UNNEST([1,3])WITHORDINALITYASa(val,idx)WHEREa.idx>=level)SELECTsubsetFROMsubsetsORDERBYcardinality(subset),subset;

如果不需要递归,也可以直接使用GENERATE_SERIES配合位运算:

WITHarrAS(SELECT[1,3]ASa)SELECT(SELECTarray_agg(a[i])FROMgenerate_series(1,array_length(a))ASiWHERE(bitpos>>(i-1))&1=1)ASsubsetFROMarr,generate_series(0,(1<<array_length(a))-1)ASbits(bitpos);

两种方法都可以输出所有子集:

  • []
  • [1]
  • [3]
  • [1, 3]

你可以根据 DuckDB 的版本和性能需求选择合适的方法。第一种递归方法更直观,第二种位运算方法通常性能更好。

我选的是第二种,如下语句把每种组合的两两异或结果算出,然后与要求的数比较。

,sas(SELECTrn,bitpos,b1a,(SELECTarray_agg(a[i])FROMgenerate_series(1,array_length(a))t(i)WHERE(bitpos>>(i-1))&1=1)ASsubsetFROMd,generate_series(1,(1<<array_length(a))-1)ASbits(bitpos))selectrn,b1a,bitpos,subset,bit_count(bitpos)fromswherelist_reduce(subset,lambda x,y :xor(x,y))=b1aorderbyrn,5;

结果如下,按压次数最少的组合已标记。

┌───────┬───────┬────────┬──────────────────┬───────────────────┐ │ rn │ b1a │ bitpos │ subset │ bit_count(bitpos) │ │ int64 │ int32 │ int64 │ int32[] │ int8 │ ├───────┼───────┼────────┼──────────────────┼───────────────────┤ │ 1 │ 6 │ 48 │ [5, 3] │ 2 │<-- │ 1 │ 6 │ 10 │ [10, 12] │ 2 │ │ 1 │ 6 │ 7 │ [8, 10, 4] │ 3 │ │ 1 │ 6 │ 61 │ [8, 4, 12, 5, 3] │ 5 │ │ 2 │ 8 │ 28 │ [17, 7, 30] │ 3 │<-- │ 2 │ 8 │ 27 │ [29, 12, 7, 30] │ 4 │ │ 3 │ 46 │ 6 │ [25, 55] │ 2 │<-- │ 3 │ 46 │ 13 │ [31, 55, 6] │ 3 │ └───────┴───────┴────────┴──────────────────┴───────────────────┘

最后按原始行号分组求最小值,再加总。

selectsum(minstep)from(selectrn,min(bit_count(bitpos))minstep--按压组合二进制数的1的个数就是按压次数fromswherelist_reduce(subset,lambda x,y :xor(x,y))=b1agroupbyrn);

对于示例数据,结果如下,和题目给出的一致

┌──────────────┐ │ sum(minstep) │ │ int128 │ ├──────────────┤ │ 7 │ └──────────────┘

对于我的正式测试数据,结果和用时如下,不算太快

┌──────────────┐ │ sum(minstep) │ │ int128 │ ├──────────────┤ │ 527 │ └──────────────┘ Run Time (s): real 0.328 user 1.588000 sys 0.052000

这里发现Advent of Code的测试题库也是有重复的,这个结果和clickhouse公众号的一致。

理论上本题用递归更合适,因为要求最少按压次数,只要求出一个解就可以退出迭代了,而全组合是穷举。第二部分题目的数据量不可能用穷举解决。

再用第一种方法试做一遍,直接使用DeepSeek的语句报错

Binder Error: Cardinality can only operate on MAPs

去掉cardinality函数输出如下,有多余的[3, 3]

┌─────────┐ │ subset │ │ int32[] │ ├─────────┤ │ [] │ │ [1] │ │ [3] │ │ [1, 3] │ │ [3, 3] │ └─────────┘

需要改成如下,规定后加的元素索引必须要大于前面最后一个的索引,不允许重复使用,才能得到正确结果。

WITHRECURSIVE subsetsAS(-- 初始:空子集SELECT[]ASsubset,1ASlevel,0lastidxUNIONALL-- 递归:逐个添加元素SELECTarray_append(subset,a.val)ASsubset,level+1ASlevel,idxFROMsubsets,UNNEST([1,2,3])WITHORDINALITYASa(val,idx)WHEREa.idx>lastidx)SELECTsubsetFROMsubsets;┌───────────┐ │ subset │ │ int32[]│ ├───────────┤ │[]│ │[1]│ │[2]│ │[3]│ │[1,2]│ │[1,3]│ │[2,3]│ │[1,2,3]│ └───────────┘

再结合本题的业务逻辑,找到就不再迭代。

,subsetsAS(-- 初始:空子集SELECTrn,[]ss,0xor_val,0ASlevel,0lastidxfromdUNIONALL-- 递归:逐个添加元素SELECTs.rn,ss||[a.val],xor(xor_val,a.val),level+1ASlevel,idxFROMsubsets s,d,unnest(a)WITHORDINALITYASa(val,idx)WHEREa.idx>lastidxands.rn=d.rnandnotexists(select1fromd d1wherexor_val=b1aands.rn=d1.rn))SELECTs.rn,xor_val,level,ssFROMsubsets s,d d1wherexor_val=b1aands.rn=d1.rnorderbys.rn,level;┌───────┬─────────┬───────┬──────────────────┐ │ rn │ xor_val │level│ ss │ │ int64 │ int32 │ int32 │ int32[]│ ├───────┼─────────┼───────┼──────────────────┤ │162[5,3]<--162[10,12]│ │163[8,10,4]│ │165[8,4,12,5,3]│ │283[17,7,30]<--284[29,12,7,30]│ │3462[25,55]<--3463[31,55,6]│ └───────┴─────────┴───────┴──────────────────┘

和前面穷举的结果完全一致。按原始行号分组求最小值,再加总。

,ras(SELECTs.rn,xor_val,level,ssFROMsubsets s,d d1wherexor_val=b1aands.rn=d1.rnorderbys.rn,level)selectsum(minl)from(selectrn,min(level)minlfromrgroupbyrn);┌───────────┐ │sum(minl)│ │ int128 │ ├───────────┤ │7│ └───────────┘

使用正式测试数据,用时反而更长

┌───────────┐ │ sum(minl) │ │ int128 │ ├───────────┤ │ 527 │ └───────────┘ Run Time (s): real 0.633 user 1.632000 sys 0.312000

尝试去掉不必要的ss,将a和b1a的数据带入subset查询,减少一次表连接,仍然不如穷举,可能是递归中not exists检查还是做了表连接的原因。

Run Time (s): real 0.472 user 1.252000 sys 0.152000

最后加了一个found标记,用分析函数找出当前rn中是否有找到的,消除not exists检查,快了。

,subsetsAS(-- 初始:空子集SELECTrn,a,b1a,0found,0xor_val,0ASlevel,0lastidxfromdUNIONALL-- 递归:逐个添加元素SELECTs.rn,s.a,s.b1a,max(s.xor_val=s.b1a)over(partitionbys.rn),xor(xor_val,a.val),level+1ASlevel,idxFROMsubsets s,unnest(a)WITHORDINALITYASa(val,idx)WHEREa.idx>lastidxandnotfound),ras(SELECTs.rn,xor_val,levelFROMsubsets swherexor_val=b1aorderbys.rn,level)selectsum(minl)from(selectrn,min(level)minlfromrgroupbyrn);┌───────────┐ │sum(minl)│ │ int128 │ ├───────────┤ │527│ └───────────┘ RunTime(s):real0.236user0.608000sys0.152000

看了一下clickhouse第一部分的解法,也是穷举。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 22:49:52

【课程设计/毕业设计】基于python房价预测系统的设计与实现机器学习的房子价值预测系统的设计与实现【附源码、数据库、万字文档】

java毕业设计-基于springboot的(源码LW部署文档全bao远程调试代码讲解等) 博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、…

作者头像 李华
网站建设 2026/4/17 20:01:35

SpringBoot + RabbitMQ + 事务状态机 实现电商订单超时自动关单

在电商系统中&#xff0c;订单超时未支付自动取消是核心场景之一 —— 用户创建订单后若长时间未付款&#xff0c;需释放库存、解冻优惠券&#xff0c;避免资源占用。传统定时轮询&#xff08;如 Quartz&#xff09;存在资源消耗大、实时性差、并发能力弱等问题&#xff0c;而基…

作者头像 李华
网站建设 2026/4/18 5:44:29

SSM283的列车火车高铁票务信息管理系统

目录SSM283列车票务信息管理系统摘要开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;SSM283列车票务信息管理系统摘要 SSM283列车票务信息管理系统是基于SSM&#xff08;SpringSpring MVCMyBatis&#xff09;框架开发的智能化铁…

作者头像 李华
网站建设 2026/4/18 16:59:52

ssm285网上书店出库入库vue图书销售

目录系统架构与功能概述入库管理模块出库与销售模块技术实现细节数据安全与优化开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统架构与功能概述 SSM285网上书店系统基于SpringSpringMVCMyBatis&#xff08;SSM&#xff09;…

作者头像 李华
网站建设 2026/4/18 21:37:09

SSM297的vue前台美食点菜订餐系统vue

目录SSM297的Vue前台美食点菜订餐系统摘要开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;SSM297的Vue前台美食点菜订餐系统摘要 该系统基于Vue.js前端框架与SSM&#xff08;SpringSpringMVCMyBatis&#xff09;后端架构开发&a…

作者头像 李华
网站建设 2026/4/23 16:36:51

房间大小的粒子加速器实现商业化应用

粒子加速器通常是巨大的结构——比如位于加利福尼亚州斯坦福的SLAC国家加速器实验室长达3.2公里。但科学家们一直在努力通过使用激光来执行加速过程&#xff0c;从而缩小这些加速器的体积。这些粒子加速器将只有一个房间大小&#xff0c;成本也会大大降低。现在&#xff0c;一家…

作者头像 李华