2025sql大赛题:仅用sql处理数独

题目内容

题目原始内容参考

https://www.ninedata.cloud/sql_sudo2025

sudoku 9_9 ( 进阶挑战 )

数据规模: 1 万 rows

使用一条 SQL 给出如下图的结果。字段 id 为自增字段的数字主键,字段 puzzle 是题目内容,由 9×9 个数字组成,问号表示未知的数字。其中 result 字段是选手需要给出数独的解。

数独求解规则

四宫格数独(普通挑战):在 4x4 的方格内填入数字 1-4 ,要求每每行每列和每组的数字不能重复。

九宫格数独(进阶挑战):在 9x9 的方格内填入数字 1-9 ,要求每行每列和每组的数字不能重复。

完成普通挑战的选手,可以进一步完成进阶挑战。进阶挑战性能得分加解题正确性得分排名前8的选手进入决赛成绩评选。

进入决赛要求解题正确率大于80%

(注:提交进阶挑战 SQL 前必须先提交普通挑战的 SQL )

SQL 要求

仅允许使用一条 SQL 语句,允许使用数据库内置函数,不允许使用存储过程/自定义函数和代码块。

SQL 执行时间不超过 5 分钟,超过 5 分钟则认为成绩无效。

提交的 SQL 不能超过 10 KB 大小

解题思路

代码测试环境:oracle11g

说明:所用的sql代码都是oracle标准功能,oracle19c兼容。

赛题示例中的 " ?",就是待填入数字的位置,为了方便说明算法,后面统一按照单元格这种名称进行描述。

看到数独这个比赛题目,首先想到的就是曾经自己的玩法。

9x9的数独,就是有81个单元格,空白单元格看成未知数,那么就是根据该单元格所在的行、列、区域的已有值,排除掉数字1-9中的八个,剩下的那个就是要填入空白单元格的值。

按照以上算法思路,首先将字符串拆解成单元格形式:加入行号、列号、区域号,按照行列区域定位每个单元格。

拆解完成后,使用oracle的model子句,实现算法描述的:根据该单元格所在的行、列、区域的已有值,排除掉数字1-9中的八个,剩下的那个就是要填入空白单元格的值。

oracle的model子句可以以类似excel表格形式进行单元格的计算,并且下次计算可以直接使用上次计算结果。要注意的是,这个思路的代码如果遇到一个单元格有两个或以上可能值,始终无法排除掉,那么就无法解出数独。

解题代码

with q as (

select

id,puzzle

from sudoku9_9)

,q2 as (

-- 构造行列区域编号,用于定位1-9的分布

select

id,puzzle,i,rowno,colno

,case when rowno in (1,2,3) and colno in (1,2,3) then 1

when rowno in (1,2,3) and colno in (4,5,6) then 2

when rowno in (1,2,3) and colno in (7,8,9) then 3

when rowno in (4,5,6) and colno in (1,2,3) then 4

when rowno in (4,5,6) and colno in (4,5,6) then 5

when rowno in (4,5,6) and colno in (7,8,9) then 6

when rowno in (7,8,9) and colno in (1,2,3) then 7

when rowno in (7,8,9) and colno in (4,5,6) then 8

when rowno in (7,8,9) and colno in (7,8,9) then 9

end areno

,to_number(case when substr(puzzle,i,1)='?' then '0' else substr(puzzle,i,1) end) c1

from (

select

id,puzzle,i

,case when i<=10 then 1

when i<=20 then 2

when i<=30 then 3

when i<=40 then 4

when i<=50 then 5

when i<=60 then 6

when i<=70 then 7

when i<=80 then 8

when i<=90 then 9

end rowno

,mod(i,10) colno

from (

-- 构造行用于拆分数独

select level i

from dual

connect by level <=89

) qr,q

)qrc where colno!=0

)

,q3 as(

-- 数独运算过程

select id,puzzle,rowno,colno,areno,c1,c1n,c2n

from q2 -- where id=2

model

partition by (id,puzzle)

dimension by (rowno,colno,areno)

measures (c1, 0 c1n, 0 c2n)

rules iterate(9)(

-- 1 标记单元格不可能的值 行、列、区域

c1n[any,any,any] = case when c1[cv(),cv(),cv()]=0 then listagg(case when c1=0 then to_number('') else c1 end) within group (order by colno) over (partition by id,rowno)

|| listagg(case when c1=0 then to_number('') else c1 end) within group (order by rowno) over (partition by id,colno)

|| listagg(case when c1=0 then to_number('') else c1 end) within group (order by rowno,colno) over (partition by id,areno)

else to_number('') end

-- 构建非重复序列

,c2n[any,any,any]=case when instr(c1n[cv(),cv(),cv()],'1')>0 then '1' end

||case when instr(c1n[cv(),cv(),cv()],'2')>0 then '2' end

||case when instr(c1n[cv(),cv(),cv()],'3')>0 then '3' end

||case when instr(c1n[cv(),cv(),cv()],'4')>0 then '4' end

||case when instr(c1n[cv(),cv(),cv()],'5')>0 then '5' end

||case when instr(c1n[cv(),cv(),cv()],'6')>0 then '6' end

||case when instr(c1n[cv(),cv(),cv()],'7')>0 then '7' end

||case when instr(c1n[cv(),cv(),cv()],'8')>0 then '8' end

||case when instr(c1n[cv(),cv(),cv()],'9')>0 then '9' end

-- 1 对排除八个可能值的无值单元格 赋值

,c1[any,any,any]=case when c1[cv(),cv(),cv()]=0 and length(c2n[cv(),cv(),cv()])=8 then

45-substr(c2n[cv(),cv(),cv()],1,1)-substr(c2n[cv(),cv(),cv()],2,1)-substr(c2n[cv(),cv(),cv()],3,1)

-substr(c2n[cv(),cv(),cv()],4,1)-substr(c2n[cv(),cv(),cv()],5,1)-substr(c2n[cv(),cv(),cv()],6,1)

-substr(c2n[cv(),cv(),cv()],7,1)-substr(c2n[cv(),cv(),cv()],8,1)

else c1[cv(),cv(),cv()] end

))

-- 输出数独结果

select id,puzzle

,listagg(case when colno=9 then c1||chr(10) else c1||'' end) within group (order by rowno,colno) result

from q3

group by id,puzzle

相关推荐
知识分享小能手2 小时前
Oracle 19c入门学习教程,从入门到精通, —— 知识点详解(1)
数据库·学习·oracle
BD_Marathon2 小时前
搭建MyBatis框架之创建MyBatis的映射文件(五)
java·数据库·mybatis
橘子真甜~2 小时前
Reids命令原理与应用5 - Redis 主从同步与高可用集群
运维·网络·数据库·redis·缓存·redis集群·redis高可用
2501_948194982 小时前
RN for OpenHarmony AnimeHub项目实战:放送时间表页面开发
数据库·redis·缓存
松涛和鸣2 小时前
DAY52 7-Segment Display/GPIO/Buttons/Interrupts/Timers/PWM
c语言·数据库·单片机·sqlite·html
想摆烂的不会研究的研究生2 小时前
每日八股——Redis(3)
数据库·redis·后端·缓存
寂寞恋上夜2 小时前
数据迁移方案怎么写:迁移策略/回滚方案/验证方法(附完整模板)
网络·数据库·oracle·markdown转xmind·deepseek思维导图
冉冰学姐2 小时前
SSM校园学习空间预约系统w314l(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·学习·ssm 框架·校园学习空间预约系统·师生双角色
360智汇云3 小时前
HULK PostgreSQL 图数据库化方案:Apache AGE 的引入与实践
数据库·postgresql·apache