利用DeepSeek改写SQLite版本的二进制位数独求解SQL

把二进制位方法用于SQLite版本有一个问题需要解决,就是用字符串代替数组存储二进制状态,我在DuckDB版本基础上,把list函数改为GROUP_CONCAT,然后将语句和如下提示发给DeepSeek、

原SQLite版本计算初始化二进制状态有错,改成如下思路,并且不用逗号分隔,用定长3位十进制字符,更新时只需要拼接,不用replace。

他给出了如下的代码

WITH RECURSIVE
  input(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..')
  ),
  digits(z, lp, bit) AS (
    VALUES('1', 1, 1)
    UNION ALL SELECT 
    CAST(lp+1 AS TEXT), lp+1, bit * 2 FROM digits WHERE lp<9
  ),
  -- 初始化行列宫的二进制状态(基于已有数字)
  init_state AS (
    SELECT 
      sud,
      (
        select GROUP_CONCAT(s ,'') from(select substr(1000+sum(bit),2)s,rn from (select bit,value/9 rn from digits, generate_series(0,80) where substr(sud,value+1,1)=z union all select 0,value from generate_series(0,8)) group by rn order by rn)
      ) as rows,
      (
        select GROUP_CONCAT(s ,'') from(select substr(1000+sum(bit),2)s,rn from (select bit,value%9 rn from digits, generate_series(0,80) where substr(sud,value+1,1)=z union all select 0,value from generate_series(0,8)) group by rn order by rn)
      ) as cols,
      (
        select GROUP_CONCAT(s ,'') from(select substr(1000+sum(bit),2)s,rn from (select bit,(value/27*3 + value%9/3) rn from digits, generate_series(0,80) where substr(sud,value+1,1)=z union all select 0,value from generate_series(0,8)) group by rn order by rn)
      ) as boxes
    FROM input
  ),
  -- 递归求解
  x(s, ind, rows, cols, boxes) AS (
    SELECT 
      sud, 
      instr(sud, '.'),
      rows,
      cols,
      boxes
    FROM init_state
    UNION ALL
    SELECT
      substr(s, 1, ind-1) || z || substr(s, ind+1),
      instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' ),
      -- 更新行的二进制状态
      substr(rows, 1, ((ind-1)/9)*3) || 
      substr(1000 + (CAST(substr(rows, ((ind-1)/9)*3+1, 3) AS INTEGER) | z.bit), 2) ||
      substr(rows, ((ind-1)/9)*3+4),
      -- 更新列的二进制状态
      substr(cols, 1, ((ind-1)%9)*3) ||
      substr(1000 + (CAST(substr(cols, ((ind-1)%9)*3+1, 3) AS INTEGER) | z.bit), 2) ||
      substr(cols, ((ind-1)%9)*3+4),
      -- 更新宫的二进制状态
      substr(boxes, 1, (((ind-1)/27)*3 + ((ind-1)%9)/3)*3) ||
      substr(1000 + (CAST(substr(boxes, (((ind-1)/27)*3 + ((ind-1)%9)/3)*3+1, 3) AS INTEGER) | z.bit), 2) ||
      substr(boxes, (((ind-1)/27)*3 + ((ind-1)%9)/3)*3+4)
    FROM x, digits AS z
    WHERE ind>0
      AND z.lp BETWEEN 1 AND 9
      -- 使用位运算检查是否可以放置数字
      AND (CAST(substr(rows, ((ind-1)/9)*3+1, 3) AS INTEGER) & z.bit) = 0
      AND (CAST(substr(cols, ((ind-1)%9)*3+1, 3) AS INTEGER) & z.bit) = 0
      AND (CAST(substr(boxes, (((ind-1)/27)*3 + ((ind-1)%9)/3)*3+1, 3) AS INTEGER) & z.bit) = 0
  )
SELECT s FROM x WHERE ind=0;

它计算原有的例子没问题。但是我把只有17个已知数的最小数独给它,却算不出来,经过调试发现,当某行全为空时,它不返回sum值,导致二进制状态缺行,再次让DeepSeek修改,他给出的解决方法是COALESCE或左连接,但实际上不能用,还是手工把它改成union all 一个行号0值序列,再做分组,此思路已改在上述代码,现在就能处理最小数独了。

把上述代码保存为 dssql2.txt,将它与原始SQLite示例比较,结果如下

-- 原有例子
sqlite> .read dssql2.txt

┌──────────────────────────────────────────────────────────────┐
│                              s                               │
├──────────────────────────────────────────────────────────────┤
│ 346251897759863124821974365195486273683712459472539681238197 │
│ 546914625738567348912                                        │
└──────────────────────────────────────────────────────────────┘
Run Time: real 3.376290 user 3.344000 sys 0.032000
sqlite> .read sqlsudoku.txt
┌──────────────────────────────────────────────────────────────┐
│                              s                               │
├──────────────────────────────────────────────────────────────┤
│ 346251897759863124821974365195486273683712459472539681238197 │
│ 546914625738567348912                                        │
└──────────────────────────────────────────────────────────────┘
Run Time: real 10.713583 user 10.660000 sys 0.028000
-- 17个已知数的最小数独
sqlite> .read sqlsudoku.txt
┌──────────────────────────────────────────────────────────────┐
│                              s                               │
├──────────────────────────────────────────────────────────────┤
│ 932567841157824963648319725576982134893146572421753689714298 │
│ 356285631497369475218                                        │
└──────────────────────────────────────────────────────────────┘
Run Time: real 72.085067 user 71.812000 sys 0.264000

sqlite> .read dssql2.txt
┌──────────────────────────────────────────────────────────────┐
│                              s                               │
├──────────────────────────────────────────────────────────────┤
│ 932567841157824963648319725576982134893146572421753689714298 │
│ 356285631497369475218                                        │
└──────────────────────────────────────────────────────────────┘
Run Time: real 21.870196 user 21.292000 sys 0.388000

可见,尽管需要把数字存在字符串,二进制位版本还是比原始版本快了3倍。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值