PostgreSQL 生成任意基数数独 - 4
标签
PostgreSQL , 数独 , 求解 , 动态规划
背景
使用《PostgreSQL 生成任意基数数独 - 3》 提供的方法,可以生成有解数独。在不知道数独答案的情况下,如何暴力破解呢?
实际上可以修改一下《PostgreSQL 生成任意基数数独 - 2》 里面的随机生成数独的函数,破解数独。
破解数独函数如下
create or replace function resolve_sudoku( vsudoku int[] -- 求解数独
) returns int[] as $$
declare res int[]; -- 结果 dims int := array_length(vsudoku,1); -- X,Y,BOX集合元素个数 dim int := sqrt(dims); -- 基数 vxyb xyb[]; -- 存储每个像素在XYB方向上未填充的元素个数 x int; -- 从xyb[]集合中,按指定方法选中一个像素。 X坐标 y int; -- 从xyb[]集合中,按指定方法选中一个像素。 Y坐标 vloops int := 2*dims; -- 计算N次(实际上就是随机多少次能覆盖到所有的值,值的取值空间为dims,通常来说执行DIMS次,能覆盖到所有的随机数) vloop int :=0; -- 计算N次计数器 cnt int := 0; -- 统计当前数独总共填充了多少个元素 rand int; -- 随机值
begin -- 求解 res := vsudoku; loop -- 生成每个像素X,Y,B方向的未知值个数 select comp_xyb(res, dim) into vxyb; -- 选择下一个要填充的像素(根据未知值个数排行,从总未知值最多,按单轴最多的位置中随机取一个位置) select ax,ay into x,y from unnest(vxyb) t where t.x+t.y+t.b <> 0 order by (t.x+t.y+t.b) desc , greatest(t.x,t.y,t.b) desc limit 1; -- 如果全部为0,0,0,说明已解完,返回res。 if not found then raise notice '计算有解,计算%次,结束。', cnt; return res; end if; -- 初始化以下计算循环次数 vloop := 0; loop -- 生成随机值 rand := 1+(random()*(dims-1))::int; -- 这轮循环无法生成并返回空 if vloop >= vloops then raise notice '本像素已循环%次,计算无解。已填充%个元素。无解数独如下: %', vloop, cnt, res; -- return res; return null; end if; -- 循环次数+1 vloop := vloop+1; -- 横向验证 perform 1 where array(select res[x][generate_series(1,dims)]) && array[rand]; if found then continue; end if; -- 纵向验证 perform 1 where array(select res[generate_series(1,dims)][y]) && array[rand]; if found then continue; end if; -- BOX验证 perform 1 where array( select res[xx][yy] from (select generate_series(((((x-1)/dim)::int)*dim)+1, ((((x-1)/dim)::int)*dim)+dim) xx) t1, (select generate_series(((((y-1)/dim)::int)*dim)+1, ((((y-1)/dim)::int)*dim)+dim) yy) t2 ) && array[rand]; if found then continue; end if; -- 这个像素值,通过验证 res[x][y] := rand; -- raise notice 'res[%][%] %', x, y, rand; -- 通过验证并跳出循环,找下一个需要填充的像素 cnt := cnt+1; exit; end loop; end loop;
end;
$$ language plpgsql strict volatile;
例子
1、首先按难易程度生成几个数独
postgres=# select gen_sudoku_question(20); gen_sudoku_question
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- {{1,6,7,9,5,8,4,3,2},{9,5,8,4,3,2,1,6,7},{4,3,2,1,6,7,9,5,8},{6,7,1,5,8,9,3,2,4},{5,8,9,3,2,4,6,7,1},{3,2,4,6,7,1,5,8,9},{7,1,6,8,9,5,2,4,3},{8,9,5,2,4,3,7,1,6},{2,4,3,7,1,6,8,9,5}} {{1,0,7,9,0,8,4,3,2},{9,0,8,0,3,2,0,6,7},{4,3,2,1,6,7,0,5,8},{6,0,1,0,8,9,0,2,4},{5,0,9,3,2,4,0,7,1},{3,2,0,6,7,1,5,8,9},{7,1,0,0,0,5,0,4,3},{0,9,5,2,4,0,7,1,6},{0,4,3,7,0,6,8,9,5}}
(2 rows) postgres=# select gen_sudoku_question(41);
NOTICE: relation "tmp_sudoku" already exists, skipping gen_sudoku_question
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- {{5,3,9,2,6,7,1,4,8},{1,4,8,5,3,9,2,6,7},{2,6,7,1,4,8,5,3,9},{9,5,3,7,2,6,8,1,4},{8,1,4,9,5,3,7,2,6},{7,2,6,8,1,4,9,5,3},{3,9,5,6,7,2,4,8,1},{4,8,1,3,9,5,6,7,2},{6,7,2,4,8,1,3,9,5}} {{5,0,0,2,0,7,1,0,8},{0,4,0,0,0,9,0,6,7},{2,0,7,0,0,0,0,0,0},{9,0,3,0,2,6,8,1,4},{0,1,0,0,0,0,7,0,6},{0,0,6,0,0,0,0,5,3},{0,9,0,6,0,2,4,0,1},{4,8,0,0,9,0,6,7,2},{6,0,2,4,0,1,0,0,5}}
(2 rows) postgres=# select gen_sudoku_question(51);
NOTICE: relation "tmp_sudoku" already exists, skipping gen_sudoku_question
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- {{3,4,5,8,1,6,2,9,7},{8,1,6,2,9,7,3,4,5},{2,9,7,3,4,5,8,1,6},{4,5,3,1,6,8,9,7,2},{1,6,8,9,7,2,4,5,3},{9,7,2,4,5,3,1,6,8},{5,3,4,6,8,1,7,2,9},{6,8,1,7,2,9,5,3,4},{7,2,9,5,3,4,6,8,1}} {{0,4,5,0,0,6,2,9,0},{8,1,0,0,0,0,0,4,0},{2,0,0,3,4,0,8,0,6},{0,0,3,1,6,8,0,0,0},{0,0,8,0,0,0,4,5,0},{0,0,0,4,0,0,1,6,0},{0,0,0,0,0,1,0,0,9},{6,0,0,7,0,0,0,3,4},{0,0,0,0,0,0,0,0,1}}
(2 rows)
2、使用上面创建的函数破解数独
填充20个值的数独基本上秒解。
postgres=# select res from (select resolve_sudoku('{{1,0,7,9,0,8,4,3,2},{9,0,8,0,3,2,0,6,7},{4,3,2,1,6,7,0,5,8},{6,0,1,0,8,9,0,2,4},{5,0,9,3,2,4,0,7,1},{3,2,0,6,7,1,5,8,9},{7,1,0,0,0,5,0,4,3},{0,9,5,2,4,0,7,1,6},{0,4,3,7,0,6,8,9,5}}'::int[]) res from generate_series(1,100) ) t where t.res is not null ;
res
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- {{1,6,7,9,5,8,4,3,2},{9,5,8,4,3,2,1,6,7},{4,3,2,1,6,7,9,5,8},{6,7,1,5,8,9,3,2,4},{5,8,9,3,2,4,6,7,1},{3,2,4,6,7,1,5,8,9},{7,1,6,8,9,5,2,4,3},{8,9,5,2,4,3,7,1,6},{2,4,3,7,1,6,8,9,5}}
(1 row)
但是对于需要填充41个,51个的,这种暴力尝试的方式,跑1000次也解不出来。
还是需要一个非常行之有效的。
目前的暴力破解存在的问题,一个值一旦确定下来(XYB方向满足约束)之后,后面就不会去修正它,从而导致了一个错误后面的计算全是浪费的。增加了破解成本。
扩展
在数据库中执行计划也与之类似,目前大多数执行计划是静态的,一旦执行计划确定下来了,后面就只能按照执行计划执行,无法中途调整。
所以,动态执行计划也成为目前很多数据库优化器突破的方向,在执行过程中,根据执行过程中的统计信息,不断修正执行计划,达到最佳的目的。
实际上,导航也与之类似,如果你根据当前的路况规划好了导航,在行驶过程中,可能某些路段发生了变化(拥堵情况),静态导航就无法修正这样的问题,还是按一开始既定的线路行驶。而动态导航,可以根据实时路况进行修正,选择下一跳。
在生产中有很多类似的例子,比如数据路由,负载均衡等等。
PostgreSQL 生成任意基数数独 - 4相关推荐
- php 输出任意一个数,php 生成任意范围的水仙花数
水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI).自恋数.自幂数.阿姆斯壮数或阿姆斯特朗数(Armst ...
- python生成订单号或生成任意序列
python生成订单号或生成任意序列 示例代码: import time# 生成订单号 def get_order_code():# 年月日时分秒+time.time()的后7位order_no = ...
- VBA实现两种方法生成任意概率分布的随机数
引子 一把武器的品质有分为最下级.下级.中级.上级.最上级五档,我希望在击杀一只怪物的时候,这把武器的掉率:最下级>下级>中级>上级>最上级,问如何设计满足上面的需求? 在游戏 ...
- python随机生成车牌_Python实现随机生成任意数量车牌号
之前做课设的时候舍友遇到了需要生成500w量级车牌号的问题,于是我便写了一个随机生成车牌号的程序,希望各位采纳. 注:Python实现 import random def chepaihao(len= ...
- crc生成多项式怎么算_利用system Verilog生成任意CRC多项式
IC君的第43篇原创文章 之前有一篇文章讲了CRC串行和并行电路的实现:CRC算法的硬件电路实现:串行电路和并行电路. 有做过类似设计的同学问:有没有办法轻松愉快地生成任意CRC多项式的电路?我们在设 ...
- 我的Python脚本——生成任意波形并存为txt
我的Python脚本--生成任意波形并存为txt 一. 脚本功能 根据采样点数,采样周期数等参数以及波形的数学表达式,生成任意波形 将波形数据转为指定位宽的二进制补码,然后存为txt 绘制原始波形和转 ...
- python批量生成图片_利用Python批量生成任意尺寸的图片
实现效果 通过源图片,在当前工作目录的/img目录下生成1000张,分别从1*1到1000*1000像素的图片. 效果如下: 目录结构 实现示例 # -*- coding: utf-8 -*- imp ...
- python批量生成图_利用Python批量生成任意尺寸的图片
实现效果 通过源图片,在当前工作目录的/img目录下生成1000张,分别从1*1到1000*1000像素的图片. 效果如下: 目录结构 实现示例 # -*- coding: utf-8 -*- imp ...
- python实现给定信号生成任意信噪比的带噪声信号
python实现给定信号生成任意信噪比的带噪声信号 产生叠加高斯白噪声的带噪语音 功能: 输入x为需加噪的信号,是一个numpy的1D张量 输入snr为设定信噪比,单位为dB,是一个32为的float ...
- 软工个人项目之生成和求解数独
软工个人项目之生成和求解数独 在这次完成个人项目的过程中,我第一次尝试了写csdn博客,用vs进行性能分析,在vs里面写单元测试,这次收获了很多.虽然还有很多需要改进的地方,但我会做得越来越好的~ 1 ...
最新文章
- 【IDAX投研中心】BCH诞生一周年 “青出于蓝而胜于蓝”吗?
- Hive学习笔记 —— Hive的体系结构
- 四个角度教你评估一个产品的用户体验好坏 | PMCAFF
- C++ int转string的几种方法比较
- 通过高速计算机网络和多媒体,计算机网络作业及答案.doc
- python gui编程 从入门到项目实战_python GUI编程 QT5开发项目实战
- 从保证业务不中断,看网关的“前世今生”
- 用java实现学生管理系统
- 反向传播的目的,及其为什么要从后向前计算梯度
- python编程代码画画_分享给大家几段有趣的代码,学会python画画可以不用自己动手啦...
- redis过期策略有哪些?内存淘汰机制有哪些?
- 几种ESB(企业服务总线)介绍
- 微信浮窗是不是服务器保存,微信浮窗,能解决小程序留存难题吗?
- 3G模块SIM5360E实现拨号上网功能
- prometheus 监控告警安装与设置
- 3D数学基础——欧拉角与万向节死锁
- 模型量化(6):Yolov5 QAT量化训练
- pycharm安装与配置Pyqt5
- 你的设计应该「所见即所得」
- 【IoT】产品设计:硬件产品外观样品设计工艺及要求(手板)
热门文章
- 自学Java怎么入门
- 软件测试流程(完整版)
- 方舟基础物品指令代码大全
- 用计算机关闭无线网络连接,我的DELL笔记本电脑无线网络已关闭,怎么进行再连接?...
- ADT版本查看,This Android SDK requires Andr...ate ADT to the latest问题
- APP性能测试之jmeter
- 用iPhone打造个人的GTD(Get Things Done)实践
- linux麒麟认证,【麒麟在线讲堂】优麒麟生物特征认证系统-03驱动开发
- 设计模式之禅(第2版)PDF资源分享
- XSD文件详解(以Maven为例)