当前位置: 首页 > news >正文

利用短整数类型和部分字符串优化DuckDB利用数组求解数独SQL

与利用定长字符串版本相比,利用整数数组的速度略慢,这是因为数组是复杂数据结构,有开销,这个开销抵消了字符串转整数的开销。
因此,它还有几处细节可以优化。
1.存储二进制位状态的rows, cols, boxes数组都保存了大整数,而在每个递归步骤都要保存当前的状态,多用了几倍的空间,考虑每个二进制不超过512,可以用转成smallintl类型来优化。
实测计算只有17个已知数的最小数独,定长字符串版本用时3.048秒,大整数数组用时4.686 秒,短整数数组用时3.212秒。
2.每步用instr从字符串找最前.位置不必要,其实每步的.位置都是确定的, 可以在第一步计算完毕,供以后读取。
3.基于第二点,每步保存的字符串不必是完整字符串,只要保存当前状态部分就够了,然后在最后一步,将它与input再合并成完整字符串。使用了这个优化,短整数数组用时2.881秒,终于反超了定长字符串版本。

WITH RECURSIVEinput(sud) AS (VALUES('9......4..5..2........1......69..1........5.24..7......1....3.....6...9....4.....')
--    VALUES('.....1..7....6..2.8..9..3...954....3..3...4..4......8......7..6.1..2....5..3..9..')),a(ins) as(select list(i::tinyint order by i) from input, range(1, 82)t(i) where sud[i]='.'), digits(z, lp, bit) AS (VALUES('1', 1, 1::smallint)UNION ALL SELECT CAST(lp+1 AS TEXT), lp+1, bit * 2 FROM digits WHERE lp<9),-- 初始化行列宫的二进制状态(基于已有数字)init_state AS (SELECT sud,(select list(s::smallint order by rn) from(select sum(bit)s,rn from(select bit,i//9 rn from digits, range(0,81) t(i) where substr(sud,i+1,1)=z union all select 0,i from range(9)t(i)) group by rn)) as rows,-- 列的二进制状态数组(select list(s::smallint order by rn) from(select sum(bit)s,rn from(select bit,i%9 rn from digits, range(0,81) t(i) where substr(sud,i+1,1)=z union all select 0,i from range(9)t(i)) group by rn)) as cols,-- 宫的二进制状态数组(select list(s::smallint order by rn) from(select sum(bit)s,rn from(select bit,(i//27*3 + i%9//3) rn from digits, range(0,81) t(i) where substr(sud,i+1,1)=z union all select 0,i from range(9)t(i)) group by rn)) as boxesFROM input),-- 递归求解x(lv, s, ind, rows, cols, boxes) AS (SELECT 1::tinyint, '', --substr(replace(sud,'.',''),1,ins[1]-1) ins[1], --instr(sud, '.'),rows,cols,boxesFROM init_state, aUNION ALLSELECT lv+1, s||z, --substr(s, 1, ind-1) || z || substr(s, ind+1),ins[lv+1], --instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' ),-- 更新行的二进制状态list_transform(rows, (val, idx) -> CASE WHEN idx = ((ind-1)//9) + 1 THEN val | z.bit ELSE val END),-- 更新列的二进制状态list_transform(cols, (val, idx) -> CASE WHEN idx = ((ind-1)%9) + 1 THEN val | z.bit ELSE val END),-- 更新宫的二进制状态list_transform(boxes, (val, idx) -> CASE WHEN idx = (((ind-1)//27)*3 + ((ind-1)%9)//3) + 1 THEN val | z.bit ELSE val END)FROM x, digits AS z, aWHERE ind>0-- AND z.lp BETWEEN 1 AND 9-- 使用位运算检查是否可以放置数字AND (rows[((ind-1)//9) + 1] & z.bit) = 0AND (cols[((ind-1)%9) + 1] & z.bit) = 0AND (boxes[(((ind-1)//27)*3 + ((ind-1)%9)//3) + 1] & z.bit) = 0)--select s from x,a where lv=len(ins)+1;, j as(select s from x,a where lv=len(ins)+1) --结果部分字符串, j2 as(select substr(s, i, 1) s, ins[i] idx from j, a , range(1, 82)t(i) where i <=len(ins)) --带位置的结果字符表, j3 as(select substr(sud, i, 1)s, i idx from input , range(1, 82)t(i) where substr(sud, i, 1)<>'.') --带位置的初始字符表select listagg(s, '' order by idx) from (from j2 union all from j3);
http://www.dtcms.com/a/589178.html

相关文章:

  • 营销型网站四大功能模版网站有源代码吗
  • 力扣81. 搜索旋转排序数组 II
  • WampServer安装教程(图文步骤)+ 下载+配置+解决图标红橙绿问题【附安装包】
  • 使用 dash 构建 mvvm 整洁架构应用
  • 跨时钟域处理
  • 2025制品管理工具选型,jfrog vs nexus vs hadess哪一款更好用?
  • 北京校园网站建设wordpress新建页面是
  • 【1.7】基于FPGA的costas环开发1——发射端信号产生模块
  • Postman 工具实现签名校验:完整操作指南与代码解析
  • AQS介绍
  • reshape的共享内存
  • 数据结构之,栈与队列
  • 【数据结构】基于哈夫曼树的数据压缩算法
  • SQLAlchemy2.0使用
  • 利用binlog2sql数据闪回实战
  • 东莞网站建设曼哈顿信科网站建设的总体设计概图
  • 算法:矩形区域不超过k的数值和
  • 算法30.0
  • 算法基础篇:(四)基础算法之前缀和
  • Nginx优化与防盗链
  • Vue-vuex 核心概念和 API
  • 分治归并算法第一弹
  • 【数据结构】哈夫曼树技术详解:原理、算法与应用
  • 贵阳网站备案在哪里网站红色
  • 个人网站公司网站区别经营区别数字货币怎么推广赚钱
  • 3GPP 各主要 Release(版本)及其发布时间和主要内容
  • RK3588同时硬解和GPU绘制16路1080P/通用其他RK系列板子/嵌入式监控系统/支持国产硬件和系统
  • BB ACS355变频器家装EMC电源滤波安装与使用指南
  • ARMV9.7 FEAT_SME2p3 视频编解码器新增指令扩展
  • 基础开发工具(下)