JAVA数独解题(九):数链法(数串、垂直)
JAVA数独解题(九):数链法(数串、垂直)
- 说明
- 图片
- 算法代码
- CalcEnum
- SuLianVerticalCalc
- SudoUtil
- 测试数据
- 输出结果
- 总结
- 代码详情
说明
参考文章:数独高级技巧:数串法的原理与应用详解(19年12月27日)
如下图所示,数字n在某一列中,只有两个空白格B1,B2(不在同宫中)存在,并且在行中也只有两个空白格B3,B4(不在同宫中)。并且两个端点都在某个宫中。则另外两个端点相交的其他宫的空白格B5,则没有数字n。
图片
算法代码
CalcEnum
在 绑定算法 中添加 属性
package com.suduku.calc.enums;import com.suduku.calc.*;
import lombok.AllArgsConstructor;
import lombok.Getter;import java.util.HashMap;
import java.util.Map;/*** 功能描述: 算法枚举 <br/>**/
@Getter
@AllArgsConstructor
public enum CalcEnum {/***/ONLY_NUM(OnlyNumCalc.class, "唯余法"),ONLY_BOX(OnlyBoxCalc.class, "摒除法"),GRID_XY(GridXYCalc.class, "单宫行列法"),SU_DUI(SuDuiCalc.class, "数对法"),X_WING(XwingCalc.class, "X-wing"),Y_WING(YwingCalc.class, "Y-wing"),XY_WING(XYwingCalc.class, "XY-wing"),YX_WING(YXwingCalc.class, "YX-wing"),XYZ_WING(XYZwingCalc.class, "XYZ-wing"),SU_LIAN_V(SuLianVerticalCalc.class, "数链垂直"), // 需要测试数据符合算法,调整顺序SU_LIAN_T(SuLianTrapezoidCalc.class, "数链梯形"),;private static final Map<Class<? extends AbstractCalc>, CalcEnum> CE_MAP = new HashMap<>(CalcEnum.values().length);static {for(CalcEnum ce : CalcEnum.values()) {CE_MAP.put(ce.getClazz(), ce);}}/*** 功能描述: 通过类,获取枚举 <br/>** @param clazz 类* @return "com.suduku.calc.enums.CalcEnum"*/public static CalcEnum indexOf(Class<? extends AbstractCalc> clazz) {return CE_MAP.get(clazz);}private final Class<? extends AbstractCalc> clazz;private final String name;}
SuLianVerticalCalc
package com.suduku.calc;import com.suduku.entity.Box;
import com.suduku.util.SudoUtil;import java.util.List;
import java.util.Map;/*** 数链-垂直(数字n在某一列中,只有两个空白格B1,B2(不在同宫中)存在,* 并且在行中也只有两个空白格B3,B4(不在同宫中)。并且两个端点都在某个宫中。* 则另外两个端点相交的其他宫的空白格B5,则没有数字n) <br/>** 测试数据:DataConstant.OTHER_SU_LIAN_V_01*/
public class SuLianVerticalCalc extends AbstractCalc {/*** 1. 遍历所有数字* 2. 遍历所有列,获取只有两个候选值有数字n的空白格B1,B2,不能在同一宫中(可能存在多列)* 3. 遍历所有行,获取只有两个候选值有数字n的空白格B3,B4,不能在同一宫中(可能存在多行)* 4. 判断是否有两个顶点在同一个宫中。* 5. 如果存在有两个顶点在同一宫中,则另外两个顶点垂直相交的另一个点是空白格,则不包含数字n*/@OverrideBox solve() {// 遍历数字for(Integer n : Box.INIT_LIST) {// 遍历所有列for (Map.Entry<Integer, List<Box>> yEntry : getYMap().entrySet()) {// 获取B1,B2两个空白格List<Box> b12List = SudoUtil.findBoxByCList(yEntry.getValue(), n);if(SudoUtil.isTwoBox(b12List)) {// 遍历所有行,获取B3,B4两个空白格for (Map.Entry<Integer, List<Box>> xEntry : getXMap().entrySet()) {List<Box> b34List = SudoUtil.findBoxByCList(xEntry.getValue(), n);if(SudoUtil.isTwoBox(b34List)) {// B1B3相交同一宫中Box clearBox = intersectAndClear(b12List.get(1), b12List.get(0), b34List.get(0), b34List.get(1), n);if(clearBox != null) {return clearBox;}// B1B4相交同一宫中clearBox = intersectAndClear(b12List.get(1), b12List.get(0), b34List.get(1), b34List.get(0), n);if(clearBox != null) {return clearBox;}// B2B3相交同一宫中clearBox = intersectAndClear(b12List.get(0), b12List.get(1), b34List.get(0), b34List.get(1), n);if(clearBox != null) {return clearBox;}// B2B4相交同一宫中clearBox = intersectAndClear(b12List.get(0), b12List.get(1), b34List.get(1), b34List.get(0), n);if(clearBox != null) {return clearBox;}}}}}}return null;}/*** 功能描述: 相交与同一宫中,并且清理数字n <br/>* * @param b1 列非相交点* @param b2 列相交点* @param b3 行相交点* @param b4 行非相交点* @param n 候选值n* @return "com.suduku.entity.Box"*/private Box intersectAndClear(Box b1, Box b2, Box b3, Box b4, Integer n) {if(b2.getG() == b3.getG()) {Box box = getBoxByXY(b1.getX(), b4.getY());if(box != null && box.isBlank() && box.getCList().contains(n)) {getListener().sendMsg("清除数字%d\n", n);box.removeCList(n);return box;}}return null;}}
SudoUtil
/*** 功能描述: 判断是否不在同一宫中的两个单元格 <br/>** @param bList 待判断单元格列表* @return "boolean"*/public static boolean isTwoBox(List<Box> bList) {return bList.size() == 2 && bList.get(0).getG() != bList.get(1).getG();}
测试数据
在 DataConstant 中添加
public static final String OTHER_X_WING_01 = "000300100500401090001028600090800001008017002010040800004085000300100040002634000";
输出结果
尝试【数链垂直 】
清除数字3
确认位置【行:1,列:6】 值为:【7】 候选值为:【】0 (3 ) 2 ( ) 9 ( ) | 1 ( ) 4 ( ){7}( ) | 6 ( ) 8 ( ) 5 ( ) | 5 ( ) 1 ( ) 4 ( ) | 8 ( ) 6 ( ) 2 ( ) | 0 (37 ) 0 (39 ) 0 (379 ) | 6 ( ) 0 (378 ) 0 (38 ) | 0 (39 ) 0 (9 ) 5 ( ) | 2 ( ) 1 ( ) 4 ( ) | 1 ( ) 6 ( ) 7 ( ) | 5 ( ) 2 ( ) 8 ( ) | 0 (34 ) 0 (349 ) 0 (39 ) | 0 (48 ) 0 (348 ) 0 (358 ) | 7 ( ) 1 ( ) 9 ( ) | 0 (58 ) 2 ( ) 6 ( ) | 2 ( ) 9 ( ) 0 (58 ) | 6 ( ) 3 ( ) 4 ( ) | 0 (58 ) 7 ( ) 1 ( ) | 0 (37 ) 5 ( ) 2 ( ) | 4 ( ) 8 ( ) 1 ( ) | 9 ( ) 6 ( ) 0 (37 ) | 0 (49 ) 0 (34 ) 6 ( ) | 2 ( ) 0 (79 ) 0 (3 ) | 1 ( ) 5 ( ) 8 ( ) | 0 (89 ) 0 (378 ) 1 ( ) | 0 (39 ) 5 ( ) 6 ( ) | 0 (347 ) 0 (34 ) 2 ( ) |
最终结果
3 ( ) 2 ( ) 9 ( ) | 1 ( ) 4 ( ) 7 ( ) | 6 ( ) 8 ( ) 5 ( ) | 5 ( ) 1 ( ) 4 ( ) | 8 ( ) 6 ( ) 2 ( ) | 3 ( ) 9 ( ) 7 ( ) | 6 ( ) 7 ( ) 8 ( ) | 3 ( ) 9 ( ) 5 ( ) | 2 ( ) 1 ( ) 4 ( ) | 1 ( ) 6 ( ) 7 ( ) | 5 ( ) 2 ( ) 8 ( ) | 4 ( ) 3 ( ) 9 ( ) | 4 ( ) 8 ( ) 3 ( ) | 7 ( ) 1 ( ) 9 ( ) | 5 ( ) 2 ( ) 6 ( ) | 2 ( ) 9 ( ) 5 ( ) | 6 ( ) 3 ( ) 4 ( ) | 8 ( ) 7 ( ) 1 ( ) | 7 ( ) 5 ( ) 2 ( ) | 4 ( ) 8 ( ) 1 ( ) | 9 ( ) 6 ( ) 3 ( ) | 9 ( ) 4 ( ) 6 ( ) | 2 ( ) 7 ( ) 3 ( ) | 1 ( ) 5 ( ) 8 ( ) | 8 ( ) 3 ( ) 1 ( ) | 9 ( ) 5 ( ) 6 ( ) | 7 ( ){4}( ) 2 ( ) | ============数独解题完成,尝试次数为:45============
总结
在编写改算法的过程中,发现了数对方法考虑的场景漏了,补充了数对的场景。
相关链接:JAVA数独解题(四):数对法
代码详情
代码地址
JAVA数独解题(九):数链法(数串、垂直)相关推荐
- JAVA数独解题(四):数对法
JAVA数独解题(四):数对法 说明 图片 算法代码 CalcEnum SuDuiCalc SudoUtil 输出结果 总结 代码详情 说明 数对:两个单元格,两个数字.两个数字在当前区域(行.列.宫 ...
- JAVA数独解题(一):框架搭建
JAVA数独解题(一):框架搭建 前言 环境 创建工程 实体类 Box Sudo 监听器 SudoListener SudoPrintImpl 核心类 SudoHandler 算法组 Abstract ...
- JAVA数独解题(五):X-wing(矩阵法)
JAVA数独解题(五):X-wing(矩阵法) 说明 图片 算法代码 CalcEnum XwingCalc YwingCalc SudoUtil 测试数据 输出结果 总结 代码详情 说明 参考文章:数 ...
- JAVA数独解题(七):XYZ-wing
JAVA数独解题(七):XYZ-wing 说明 图片 算法代码 CalcEnum XYZwingCalc SudoUtil 测试数据 输出结果 总结 代码详情 说明 参考文章:数独高级技巧:XYZ-w ...
- 数独高阶技巧入门之四:简单异数链
一.XY-Wing 图1 XY-Wing01 图1中,R2绿色三个双值格构成三链数,则在该行中X.Y.Z三个数字只能存在于绿色三格中.如果我们把三链数构成的直线掰弯,比如掰成像下图中的两种情况, Y ...
- Java多线程学习九:怎样确定线程数量及CPU 核心数和线程数的关系||如何定制自己的线程池
调整线程池中的线程数量的最主要的目的是为了充分并合理地使用 CPU 和内存等资源,从而最大限度地提高程序的性能.在实际工作中,我们需要根据任务类型的不同选择对应的策略. CPU 密集型任务 首先,我们 ...
- 用java实现:有15个红球和15个绿球排成一圈,从第1个球开始数,当数到13个球时就取出此球,然后再从下一个球开始数,当再数到13时又取出。怎样循环取出所有的红球?
java语言实现:有15个红球和15个绿球排成一圈,从第1个球开始数,当数到13个球时就取出此球,然后再从下一个球开始数,当再数到13时又取出.如此循环进行直到仅剩15个球为止,怎样排法才能使每次取出 ...
- Java 递归解决 quot;仅仅能两数相乘的计算器计算x^yquot; 问题
Java 递归解决 "仅仅能两数相乘的计算器计算x^y" 问题 /*** 求一个数的乘方* 求x^y,y是一个正整数. 设计算器仅仅能计算两数相乘,不能一次计算n个数相乘. * 知 ...
- java统计行列和字数的函数_JAVA使用POI获取Excel的列数与行数
前言 报表输出是Java应用开发中经常涉及的内容,而一般的报表往往缺乏通用性,不方便用户进行个性化编辑.Java程序由于其跨平台特性,不能直接操纵Excel.因此,本文探讨一下POI视线Java程序进 ...
最新文章
- 解决前后端base64编码传递时的中文乱码问题
- kaggle账号_机器学习竞赛入门--kaggle篇
- 基于 MVP 的 Android 组件化开发框架实践
- python基础教程: 自定义函数
- 2.关于QT中数据库操作,简单数据库连接操作,数据库的增删改查,QSqlTableModel和QTableView,事务操作,关于QItemDelegate 代理
- [vue] 父子组件间传值
- linux下运行程序后出现段错误的原因和解决案例
- idea ssm框架 mysql_IDEA 2017 整合SSM框架(使用Maven创建工程)
- Python简记--函数
- σ 代数与测度(measures)
- java正则匹配买火车票_matlab的正则表达式
- 人类(行为)动力学(1)——初步了解
- matlab imrotate中心,MATLAB imrotate函数的用法
- 梅西大学研究员创造出新3D打印系统 用螺杆作为进料机构挤出颗粒
- VS2015重装Team explorer报错
- 一部区块链创业者的“燃点” | 《8问》
- (Raw/High) P-Code Ghidra使用的中间表示语言
- FTTB+NAT+DHCP+pppoe+CBAC+*** client+Authentication AAA
- PHP爬虫,提取网站中的关键词,用一次正则匹配,然后再PHP数组的操作
- 高并发量网站解决方案