最近看朋友在玩消灭星星(pop start),想起当年还不是彩屏手机的时候,我喜欢玩数独游戏.数独(Sudoku)又称九宫格,据说来头很大,起源于河图洛书,相信大家都有玩过.百度九宫格,

百度百科最后有提到芬兰数学家因卡拉花费3个月设计出了世界上迄今难度最大的九宫格游戏,而且它只有一个答案,就想挑战一下.水平有限花了2天时间问题解决,速度还行2秒内就

能解答,发现还是比较简单的,大概的分为两段,第一段是找到唯一的那些值填上做为永久值,然后再找唯一值做为永久值,直到找不到唯一值.第二段通过回溯,把可能的值按顺序尝试,不

合适就回退,至到找到最终合适的.

以下脚本及解释:

DECLARE

--定义数独行列

TYPE T_ROW IS VARRAY(9) OF NUMBER;

TYPE T_COL_ROW IS VARRAY(9) OF T_ROW;

--初始化数独

v_init   T_COL_ROW := T_COL_ROW(T_ROW(8, 0, 0, 0, 0, 0, 0, 0, 0),

T_ROW(0, 0, 3, 6, 0, 0, 0, 0, 0),

T_ROW(0, 7, 0, 0, 9, 0, 2, 0, 0),

T_ROW(0, 5, 0, 0, 0, 7, 0, 0, 0),

T_ROW(0, 0, 0, 0, 4, 5, 7, 0, 0),

T_ROW(0, 0, 0, 1, 0, 0, 0, 3, 0),

T_ROW(0, 0, 1, 0, 0, 0, 0, 6, 8),

T_ROW(0, 0, 8, 5, 0, 0, 0, 1, 0),

T_ROW(0, 9, 0, 0, 0, 0, 4, 0, 0));

--用以存放答案

v_result T_COL_ROW;

--定义一个用以计算小宫里面的同组数据的位置

TYPE T_X IS VARRAY(2) OF NUMBER;

TYPE T_Y IS VARRAY(3) OF T_X;

--用以根据相对位置,算出同组数据的绝对位置

v_xy T_Y := T_Y(T_X(1, 2), T_X(-1, 1), T_X(-1, -2));

x integer;

y integer;

--定义每个点的可能值,i存放列位置,j存放行位置,val存放可能值(可能值里面存放的是多个值,根据cur确认当前是那个),cur的值用于从val中找到当前值

TYPE T_POS IS record(

i   number,

j   number,

val varchar2(10),

cur number);

TYPE T_SEL IS TABLE OF T_POS INDEX BY BINARY_INTEGER;

v_sel T_SEL;

v_n         varchar2(10);

v_flag      number := 1;

v_sel_count number := 0;

v_hs        number := 0;

BEGIN

--打印问题数独

dbms_output.put_line('问题:');

FOR i IN 1 .. v_init.COUNT LOOP

FOR j IN 1 .. v_init(i).COUNT LOOP

dbms_output.put(v_init(i) (j) || '  ');

END LOOP;

dbms_output.put_line('');

END LOOP;

--通过循环找唯一值,把唯一值做为永久值,直到找不到唯一值

while v_flag = 1 loop

v_flag := 0;

v_sel.delete;

FOR i IN 1 .. v_init.COUNT LOOP

FOR j IN 1 .. v_init(i).COUNT LOOP

--v_init(i) (j) = 0的是用来填答案的,其它就是永久值

if v_init(i) (j) = 0 then

v_n := '';

--x,y是用来计算除行,列之后还在去对比的同组中的4个值

x := case

when mod(i, 3) = 0 then

3

else

mod(i, 3)

end;

y := case

when mod(j, 3) = 0 then

3

else

mod(j, 3)

end;

--通过循环找到可能值,把可能的值存入v_n

for k in 1 .. 9 loop

if k not in

(--行

v_init(i) (1),

v_init(i) (2),

v_init(i) (3),

v_init(i) (4),

v_init(i) (5),

v_init(i) (6),

v_init(i) (7),

v_init(i) (8),

v_init(i) (9),

--列

v_init(1) (j),

v_init(2) (j),

v_init(3) (j),

v_init(4) (j),

v_init(5) (j),

v_init(6) (j),

v_init(7) (j),

v_init(8) (j),

v_init(9) (j),

--同组另外的四个要对比的值

v_init(i + v_xy(x) (1)) (j + v_xy(y) (1)),

v_init(i + v_xy(x) (1)) (j + v_xy(y) (2)),

v_init(i + v_xy(x) (2)) (j + v_xy(y) (1)),

v_init(i + v_xy(x) (2)) (j + v_xy(y) (2))) then

begin

v_n := v_n || k;

end;

end if;

end loop;

--把可能值的位置,值存入队列

v_sel_count := v_sel.count + 1;

v_sel(v_sel_count).i := i;

v_sel(v_sel_count).j := j;

v_sel(v_sel_count).val := v_n;

v_sel(v_sel_count).cur := 1;

--如果v_n=1就是唯一值,把这个值永久化,并把v_flag设为1用以再循环一次

--如果v_n=0说明在此位置没有任何合适的值,说明这个数独开始的数据有问题

if length(v_n) = 1 then

v_init(i)(j) := to_number(v_n);

v_flag := 1;

elsif length(v_n) = 0 then

dbms_output.put_line('数独初始化的数据错误!');

exit;

end if;

end if;

END LOOP;

END LOOP;

end loop;

--把做过唯一值永久化后的数据赋值给答案数独

v_result := v_init;

--开始回溯算法通过可能值找最终答案

while v_hs < v_sel.COUNT LOOP

v_hs := v_hs + 1;

--x,y是用来计算除行,列之后还在去对比的同组中的4个值

x := case

when mod(v_sel(v_hs).i, 3) = 0 then

3

else

mod(v_sel(v_hs).i, 3)

end;

y := case

when mod(v_sel(v_hs).j, 3) = 0 then

3

else

mod(v_sel(v_hs).j, 3)

end;

--判断当前值是否合适,如果不合适,当前位置的可能值向后推进一位,如果当前位置的值已经用完,再后回退,上一层的可能值推进

if to_number(substr(v_sel(v_hs).val, v_sel(v_hs).cur, 1)) in

(v_result(v_sel(v_hs).i) (1),

v_result(v_sel(v_hs).i) (2),

v_result(v_sel(v_hs).i) (3),

v_result(v_sel(v_hs).i) (4),

v_result(v_sel(v_hs).i) (5),

v_result(v_sel(v_hs).i) (6),

v_result(v_sel(v_hs).i) (7),

v_result(v_sel(v_hs).i) (8),

v_result(v_sel(v_hs).i) (9),

v_result(1) (v_sel(v_hs).j),

v_result(2) (v_sel(v_hs).j),

v_result(3) (v_sel(v_hs).j),

v_result(4) (v_sel(v_hs).j),

v_result(5) (v_sel(v_hs).j),

v_result(6) (v_sel(v_hs).j),

v_result(7) (v_sel(v_hs).j),

v_result(8) (v_sel(v_hs).j),

v_result(9) (v_sel(v_hs).j),

v_result(v_sel(v_hs).i + v_xy(x) (1)) (v_sel(v_hs).j + v_xy(y) (1)),

v_result(v_sel(v_hs).i + v_xy(x) (1)) (v_sel(v_hs).j + v_xy(y) (2)),

v_result(v_sel(v_hs).i + v_xy(x) (2)) (v_sel(v_hs).j + v_xy(y) (1)),

v_result(v_sel(v_hs).i + v_xy(x) (2)) (v_sel(v_hs).j + v_xy(y) (2))) then

if v_sel(v_hs).cur < length(v_sel(v_hs).val) then

begin

v_sel(v_hs).cur := v_sel(v_hs).cur + 1;

v_hs := v_hs - 1;

end;

else

if v_hs > 1 then

v_result(v_sel(v_hs).i)(v_sel(v_hs).j) := 0;

v_sel(v_hs).cur := 1;

v_hs := v_hs - 2;

else

dbms_output.put_line('数独初始化的数据错误!');

exit;

end if;

end if;

else

v_result(v_sel(v_hs).i)(v_sel(v_hs).j) := to_number(substr(v_sel(v_hs).val,

v_sel(v_hs).cur,

1));

end if;

END LOOP;

--打印答案数独

dbms_output.put_line('答案:');

FOR i IN 1 .. v_result.COUNT LOOP

FOR j IN 1 .. v_result(i).COUNT LOOP

dbms_output.put(v_result(i) (j) || '  ');

END LOOP;

dbms_output.put_line('');

END LOOP;

END;

备注:

另外再放两个数独,有兴趣的可以测试.

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0)

---------------------------------------

(0, 6, 2, 0, 0, 0, 5, 0, 0),

(3, 5, 0, 0, 0, 0, 0, 0, 7),

(0, 0, 8, 0, 1, 5, 0, 4, 0),

(0, 0, 0, 0, 6, 0, 9, 0, 8),

(9, 0, 0, 0, 0, 0, 0, 2, 0),

(0, 2, 5, 0, 9, 0, 0, 0, 0),

(5, 0, 0, 0, 3, 0, 7, 0, 0),

(0, 8, 0, 0, 0, 0, 0, 5, 6),

(0, 0, 9, 0, 0, 0, 8, 0, 4)

数独用计算机控制比数学家还厉害,用pl/sql解决芬兰数学家因卡拉设计的最难数独...相关推荐

  1. 用pl/sql解决芬兰数学家因卡拉设计的最难数独

          最近看朋友在玩消灭星星(pop start),想起当年还不是彩屏手机的时候,我喜欢玩数独游戏.数独(Sudoku)又称九宫格,据说来头很大,起源于河图洛书,相信大家都有玩过.百度九宫格, ...

  2. 数独用计算机控制比数学家还厉害,比数独更烧脑的数学游戏,让娃练就最强大脑!...

    原标题:比数独更烧脑的数学游戏,让娃练就最强大脑! 在很多人眼里: 会玩数独 = 高智商 虽然规则简单,但却变幻无穷,充满乐趣,所以爸爸妈妈们都在用数独来锻炼孩子脑力,训练数学思维. 之前,阿木也专门 ...

  3. 解读新突破“中国量子计算机”,真比神威·太湖之光还厉害?

    本文来自AI新媒体量子位(QbitAI) 今天中科院微信发布了一个"重磅消息":中国量子计算机诞生. 这么说多少有一点夸张. 这件事实际上是中科大潘建伟.陆朝阳.朱晓波和浙大王浩华 ...

  4. 在互联网领域他比马化腾还厉害

    在互联网上什么事情都可能发生,现在你还是某个领域的老大,下一秒就可能发生变化,今天我们将的这个故事的主人公在某个方面比当年马化腾还厉害. 腾讯QQ当年为获得1千万用户花了一年零四个月,而成都品果科技有 ...

  5. Python来处理数独游戏(含世界最难数独示例)

    数独(sudoku)是一种填数字的游戏,在一个9*9的九宫格里面推导出剩余的数字,要求每行.每列.每宫(3*3)的数字均包含1~9,且不重复! 另:世界最难数独(题目中的最后一个数独)被江苏扬州一位农 ...

  6. winform,wpf全屏 还显示任务栏的解决方法

    winform,wpf全屏 还显示任务栏的解决方法 参考文章: (1)winform,wpf全屏 还显示任务栏的解决方法 (2)https://www.cnblogs.com/Viki/archive ...

  7. office2016激活后还显示激活页面的解决办法

    win10系统的office16通过Office激活工具激活之后,但是打开之后还会出现提示"让我们开始吧"的激活的页面, 1.office2016激活后还显示激活页面的解决办法 以 ...

  8. 无数学不华为?人工智能时代的数学家还将走得更远

    进驻欧亚大陆之北,俄罗斯联邦共和国--1996 年一无所获,1997 年一无所获,1998 年依然一无所获,1999 年勉强接到第一笔买单--38 美元. 尽管折戟多年,一家中国公司却于此地招募数十位 ...

  9. 机器人鸣人是哪一集_火影里的五个机器人,第一个比鸣人还厉害,机器丁次你都没见过...

    火影虽然是一部讲述众多忍者们的热血故事,但是火影里的时代并不是和古代一样,里面的生活是和现在的我们一样,在动漫里的忍者也是住的高楼,随时打电话,生病了也要去医院,也会肚子饿,也要一天三顿饭.只是火影里 ...

  10. 万万想不到:吸烟的辐射量比原子弹爆炸点还厉害!

    全世界只有3.14 % 的人关注了 青少年数学之旅 近日,外国视频网站上一段关于世界上辐射最高地点的短片火了起来.片中,一位外国小哥亲身探秘了那些广为人知的辐射地点如切尔诺贝利.福岛核电站等,并且给出 ...

最新文章

  1. 基于深度学习方法的图像分割,差距不止一点点
  2. IIRF重写在asp.net4.0+IIS6中部分失败的解决方案
  3. 鸿蒙怎么运行安卓应用,华为:安卓生态应用可在部分鸿蒙设备上运行
  4. java spring mvc 上传_Java Spring MVC 上传下载文件配置及controller方法详解
  5. 图片加载框架Picasso - 源码分析
  6. OpenCV图像分割-watershed
  7. linux java jar打包_【Java】Java程序打包成jar包在Linux上运行
  8. Android 向服务器发送XML数据及调用webservice
  9. 解读设计模式----策略模式(Strategy Pattern)
  10. Django周总结一
  11. Jmeter多机联合产生负载 (转)
  12. 09月28日 pytorch与resnet(五) 转移学习
  13. 新手学计算机编程怎么入门 从哪学起
  14. 编写单片机中断程序的注意事项 成都电气开发
  15. A*算法之野人传教士问题 python解法
  16. Android Studio安装和使用教程(全文图解)
  17. Remix部署契约时出现错误:creation of Ballot errored: Error encoding arguments: Error: expected array value (ar
  18. 盘点3大智能家居系统|苹果HomeKit、亚马逊Alexa、谷歌Home?
  19. 参加51CTO学院软考培训感想
  20. table数据刷新;v-if刷新el-table表格

热门文章

  1. 英特尔固态硬盘测试软件,Intel SSD Toolbox
  2. 动感标题文字快闪(闪白特效)开场PR模板MOGRT
  3. 华为JAVA编程规范
  4. xp查看计算机mac地址查询,如何查看mac地址 xp系统查看查询mac地址方法介绍
  5. 人脸识别Demo解析C#
  6. 内网安全“小迪安全课堂笔记”域横向
  7. Xmind 2022精彩体验---什么叫流程图
  8. 用IDM快速下载百度云文件
  9. COLOR_CODE
  10. WebRAY网站检查技术支撑平台的实践