SudokuSolver 2.4 程序实现

本次版本实现了 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析 里发现的第三个不完全收缩 grp 算法 thirdGreenWorld。

CQuizDealer 类声明部分的修改

class CQuizDealer
{
public:
...
void run(ulong tilsteps = 0);
void mode(std::string& ex) {
size_t pos = ex.find_first_not_of(" \t");
if (pos != std::string::npos) {
ex.erase(0, pos);
m_mode = (u8)strtoul(ex.c_str(), 0, 10);
}
printf("Working mode:%d (1:grp-only; 2:ply-only; other:both grp and ply)\n", (int)m_mode);
}
...
private:
...
CQuizDealer() : m_state(STA_UNLOADED), ..., m_mode(0) {};
...
bool completeShrinkByGrp(u8* pGrp);
u8 incompleteShrinkByGrp(u8* pGrp);
u8 firstGreenWorld(u8* pGrp);
u8 incompleteShrinkBy1GW(u8 valSum, u8* pCelSumExs, u8* pGrp);
bool sameCandidates(u8 cel1, u8 cel2);
u8 anotherGreenWorld(u8* pGrp);
u8 incompleteShrinkByAGW(u8 times, u8* pTimesVals, u8* pValsCells, u8* pGrp);
u8 thirdGreenWorld(u8* pGrp);
u8 incompleteShrinkBy3GW(u8 sum, std::set<u8>& valSet, u8* pGrp);
bool unionValsByCombi(u8 sum, u8* pCombi, u8* pGrp, std::set<u8>& unionSet);
...
ulong m_steps;
u8 m_mode; // 1:grp-only; 2:ply-only; other:both
...
};

去掉了 setOnlyGrpMode 接口,新增了 mode 接口,相应地,原先的 onlygrp 命令换成了 mode [1|2|0] 命令。

增加了 thirdGreenWorld 等接口。

filterCandidates 接口的小修改

u8 CQuizDealer::filterCandidates()
{
incSteps();
u8 ret = RET_PENDING;
if (m_mode != 2) {
for (u8 row = 0; row < 9; ++row)
if (ret = filterRowGroup(row))
return ret;
for (u8 col = 0; col < 9; ++col)
if (ret = filterColGroup(col))
return ret;
for (u8 blk = 0; blk < 9; ++blk)
if (ret = filterBlkGroup(blk))
return ret;
}
if (m_mode != 1) {
for (u8 row = 0; row < 9; ++row) {
ret = filterRowCandidatesEx(row);
if (IsDone(ret))
return ret;
}
for (u8 col = 0; col < 9; ++col) {
ret = filterColCandidatesEx(col);
if (IsDone(ret))
return ret;
}
}
if (ret == RET_SHRUNKEN) {
printf("incomplete shrink met, filter again\n");
return filterCandidates();
}
return ret;
}

修改后,可以只使用 grp 算法求解,也可以只使用 ply 算法求解,缺省是两者都用。

从旧的 filterOneGroup 接口实现中提炼出 firstGreenWorld

 1 u8 CQuizDealer::firstGreenWorld(u8* pGrp)
2 {
3 u8 size = pGrp[0];
4 u8 celSumExs[100] = {0};
5 for (u8 idx = 1; idx <= size; ++idx) {
6 u8 valSum = m_seqCell[pGrp[idx]].candidates[0];
7 u8 base = valSum * 10;
8 celSumExs[base] += 1;
9 u8 pos = base + celSumExs[base];
10 celSumExs[pos] = pGrp[idx];
11 }
12 for (u8 idx = 2; idx <= 6; ++idx) {
13 u8 ret = incompleteShrinkBy1GW(idx, celSumExs, pGrp);
14 if (ret != RET_PENDING)
15 return ret;
16 }
17 return RET_PENDING;
18 }

旧 incompleteShrinkByGrp 改为 incompleteShrinkBy1GW

 1 u8 CQuizDealer::incompleteShrinkBy1GW(u8 valSum, u8* pCelSumExs, u8* pGrp)
2 {
3 u8 base = valSum * 10;
4 if (pCelSumExs[base] < valSum)
5 return RET_PENDING;
6 u8 itemSum = 0;
7 Item items[9];
8 for (u8 pos = 1; pos <= pCelSumExs[base]; ++pos) {
9 u8 idx = 0;
10 for (; idx < itemSum; ++idx)
11 if (sameCandidates(pCelSumExs[base + pos], items[idx].celIdxs[0])) {
12 items[idx].celIdxs[items[idx].sameSum] = pCelSumExs[base + pos];
13 items[idx].sameSum++;
14 break;
15 }
16 if (idx == itemSum) {
17 items[itemSum].sameSum = 1;
18 items[itemSum].celIdxs[0] = pCelSumExs[base + pos];
19 ++itemSum;
20 }
21 }
22 for (u8 idx = 0; idx < itemSum; ++idx) {
23 if (items[idx].sameSum > valSum)
24 return RET_WRONG;
25 }
26 bool shrunken = false;
27 for (u8 idx = 0; idx < itemSum; ++idx) {
28 if (items[idx].sameSum < valSum)
29 continue;
30 for (u8 pos = 1; pos <= pGrp[0]; ++pos) {
31 if (inSet(pGrp[pos], (u8*)&(items[idx])))
32 continue;
33 u8 isVals[10] = {0};
34 u8 cel1 = items[idx].celIdxs[0];
35 u8 cel2 = pGrp[pos];
36 intersection(m_seqCell[cel1].candidates, m_seqCell[cel2].candidates, isVals);
37 if (isVals[0] == 0)
38 continue;
39 shrunken = true;
40 for (u8 valIdx = 1; valIdx <= isVals[0]; ++valIdx) {
41 if (!removeVal(m_seqCell[cel2].candidates, isVals[valIdx]))
42 return RET_WRONG;
43 else
44 printf("1GW: %d shrunken out of [%d,%d]\n", (int)isVals[valIdx], (int)cel2 / 9 + 1, (int)cel2 % 9 + 1);
45 }
46 }
47 }
48 return (shrunken ? RET_SHRUNKEN : RET_PENDING);
49 }

新的 incompleteShrinkByGrp 接口实现

 1 u8 CQuizDealer::incompleteShrinkByGrp(u8* pGrp)
2 {
3 u8 ret = firstGreenWorld(pGrp);
4 if (ret != RET_PENDING)
5 return ret;
6 ret = anotherGreenWorld(pGrp);
7 if (ret != RET_PENDING)
8 return ret;
9 return thirdGreenWorld(pGrp);
10 }

新的 filterOneGroup 接口实现

u8 CQuizDealer::filterOneGroup(u8* pGrp)
{
return (completeShrinkByGrp(pGrp) ? RET_OK : incompleteShrinkByGrp(pGrp));
}

incompleteShrinkByAGW 接口实现的 bug 修改

u8 CQuizDealer::incompleteShrinkByAGW(u8 times, u8* pTimesVals, u8* pValsCells, u8* pGrp)
{
...
while (true) {
u8 celSet[10] = {0};
u8 valSet[10] = {0};
if (matchValsCells(times, combi, pTimesVals, pValsCells, celSet, valSet)) {
valSet[0] = times;
bool shrunken = false;
for (u8 idx = 1; idx <= times; ++idx) {
...
if (candiSum < times) {
printf("2GW: [%d,%d] candidates %d lower than times %d!\n", (int)(cel / 9 + 1), (int)(cel % 9 + 1), (int)candiSum, (int)times);
return RET_WRONG;
}
shrunken = true;
for (u8 pos = 1; pos <= m_seqCell[cel].candidates[0];) {
u8 val = m_seqCell[cel].candidates[pos];
if (inSet(val, valSet))
++pos;
else {
removeVal(m_seqCell[cel].candidates, val);
printf("2GW: %d shrunken out of [%d,%d]\n", (int)val, (int)(cel / 9 + 1), (int)(cel % 9 + 1));
}
}
}
...
}
if (!move2NextCombi(times, combi))
break;
}
return RET_PENDING;
}

新增 thirdGreenWorld 接口实现

 1 u8 CQuizDealer::thirdGreenWorld(u8* pGrp)
2 {
3 u8 grpSize = pGrp[0];
4 std::set<u8> valSet;
5 u8 lowSum = 9, highSum = 0;
6 for (u8 idx = 1; idx <= grpSize; ++idx) {
7 u8 valSum = m_seqCell[pGrp[idx]].candidates[0];
8 if (valSum < lowSum)
9 lowSum = valSum;
10 if (valSum > highSum)
11 highSum = valSum;
12 for (u8 vidx = 1; vidx <= valSum; ++vidx) {
13 u8 val = m_seqCell[pGrp[idx]].candidates[vidx];
14 valSet.insert(val);
15 }
16 }
17 if (valSet.size() != grpSize) {
18 printf("3GW: shrink went wrong\n");
19 return RET_WRONG;
20 }
21 if (highSum == valSet.size())
22 --highSum;
23 for (u8 sum = lowSum; sum <= highSum; ++sum) {
24 u8 ret = incompleteShrinkBy3GW(sum, valSet, pGrp);
25 if (ret != RET_PENDING)
26 return ret;
27 }
28 return RET_PENDING;
29 }

新增 incompleteShrinkBy3GW 接口实现

 1 u8 CQuizDealer::incompleteShrinkBy3GW(u8 sum, std::set<u8>& valSet, u8* pGrp)
2 {
3 u8 combi[10] = {0};
4 combi[0] = pGrp[0];
5 for (u8 idx = 0; idx < sum; ++idx)
6 combi[idx + 1] = idx;
7 while (true) {
8 std::set<u8> unionSet;
9 if (unionValsByCombi(sum, combi, pGrp, unionSet)) {
10 u8 compSet[10] = {0};
11 for (std::set<u8>::iterator it = valSet.begin(); it != valSet.end(); ++it)
12 if (unionSet.find(*it) == unionSet.end()) {
13 compSet[0] += 1;
14 compSet[compSet[0]] = *it;
15 }
16 combi[0] = sum; // for soon calling inSet properly
17 u8 cells[10] = {0};
18 for (u8 pos = 0; pos < pGrp[0]; ++pos) {
19 if (!inSet(pos, combi)) {
20 cells[0] += 1;
21 cells[cells[0]] = pos;
22 }
23 }
24 combi[0] = pGrp[0]; //back again
25 bool shrunken = false;
26 for (u8 idx = 1; idx <= cells[0]; ++idx) {
27 u8 pos = pGrp[cells[idx] + 1];
28 for (u8 inn = 1; inn <= m_seqCell[pos].candidates[0];) {
29 u8 val = m_seqCell[pos].candidates[inn];
30 if (inSet(val, compSet))
31 ++inn;
32 else {
33 shrunken = true;
34 removeVal(m_seqCell[pos].candidates, val);
35 printf("3GW: %d shrunken out of [%d,%d]\n", (int)val, (int)pos / 9 + 1, (int)pos % 9 + 1);
36 }
37 }
38 }
39 if (shrunken)
40 return RET_SHRUNKEN;
41 }
42 if (!move2NextCombi(sum, combi))
43 break;
44 }
45 return RET_PENDING;
46 }

新增 unionValsByCombi 接口实现

 1 bool CQuizDealer::unionValsByCombi(u8 sum, u8* pCombi, u8* pGrp, std::set<u8>& unionSet)
2 {
3 for (u8 idx = 1; idx <= sum; ++idx) {
4 u8 pos = pGrp[pCombi[idx] + 1];
5 u8 valSum = m_seqCell[pos].candidates[0];
6 if (valSum > sum)
7 return false;
8 for (u8 vidx = 1; vidx <= valSum; ++vidx) {
9 u8 val = m_seqCell[pos].candidates[vidx];
10 unionSet.insert(val);
11 }
12 if (unionSet.size() > sum)
13 return false;
14 }
15 return (unionSet.size() == sum);
16 }

其他小修改

// 1.0 2021/9/20
// 2.0 2021/10/2
// 2.1 2021/10/4
// 2.2 2021/10/10
// 2.3 2021/10/17
#define STR_VER "Sudoku Solver 2.4 2021/10/19 by readalps\n\n" void showOrderList()
{
printf(STR_VER);
printf("Order List:\n");
printf("load-quiz <file>: load quiz from file\n");
printf("show: show quiz info\n");
printf("mode [1|2|0]: query or change working mode\n");
printf("step: step forward\n");
printf("run: run till the end or a new solution met\n");
printf("runtil <steps>: run till certain steps run\n");
printf("bye: quit\n");
} void dealOrder(std::string& strOrder)
{
std::string strEx;
if ("bye" == strOrder)
setQuit();
else if (matchPrefixEx(strOrder, "load-quiz ", strEx))
CQuizDealer::instance()->loadQuiz(strEx);
else if ("show" == strOrder)
CQuizDealer::instance()->showQuiz();
else if (matchPrefixEx(strOrder, "mode", strEx))
CQuizDealer::instance()->mode(strEx);
else if ("step" == strOrder)
CQuizDealer::instance()->step();
else if ("run" == strOrder)
CQuizDealer::instance()->run();
else if (matchPrefixEx(strOrder, "runtil ", strEx)) {
ulong tilsteps = strtoul(strEx.c_str(), 0, 10);
CQuizDealer::instance()->run(tilsteps);
}
else
showOrderList();
}

实例分析

“最难”数独题

继续以 SudokuSolver 1.0:用C++实现的数独解题程序 【二】 里试验过的“最难”数独题为例做分析。

D:\read\num\Release>sudoku.exe

Order please:

Sudoku Solver 2.4 2021/10/19 by readalps

Order List:
load-quiz <file>: load quiz from file
show: show quiz info
mode [1|2|0]: query or change working mode
step: step forward
run: run till the end or a new solution met
runtil <steps>: run till certain steps run
bye: quit Order please:
load-quiz s.txt
Quiz loaded. Order please:
run
...
1014) col 8 complete shrunken by group
1017) Guess [1,6] level 8 at 1 out of 2
1018) row 3 complete shrunken by group
1020) row 3 complete shrunken by group
1GW: 8 shrunken out of [2,7]
1022) row 2 incomplete shrunken by group
1023) Guess [1,8] level 9 at 1 out of 2
1026) row 9 complete shrunken by group
1028) col 6 complete shrunken by group
1031) Guess [2,5] level 10 at 1 out of 2
1034) shrinking 4 from [6,3] went wrong
1035) Forward guess [2,5] level 10 at 2 out of 2
812 753 649
943 682 175
675 491 283 154 237 896
369 845 721
287 169 534 521 974 368
438 526 917
796 318 452 Done [steps:1040, solution sum:1].
Run time: 430 milliseconds; steps: 1040, solution sum: 1. Order please:

第二次 run 命令的输出信息为:

run
...
1GW: 2 shrunken out of [5,1]
1GW: 9 shrunken out of [5,1]
1GW: 2 shrunken out of [5,2]
1GW: 2 shrunken out of [5,4]
1GW: 9 shrunken out of [5,4]
1GW: 2 shrunken out of [5,8]
1GW: 9 shrunken out of [5,8]
1698) row 5 incomplete shrunken by group
1699) Guess [1,3] level 6 at 1 out of 2
1703) row 1 complete shrunken by group
1705) row 2 complete shrunken by group
1707) row 4 complete shrunken by group
1707) shrinking 9 from blk[5,1] went wrong
1708) Forward guess [1,3] level 6 at 2 out of 2
1709) shrinking 2 from [4,9] went wrong
1710) No more solution (solution sum is 1).
809 000 306
503 600 800
076 090 250 054 007 120
002 045 789
000 100 635 001 000 568
008 500 910
090 000 400 Invalid quiz [steps:1710] - no more solution (solution sum is 1)
Run time: 265 milliseconds; steps: 1710, solution sum: 1. Order please:

从输出的完整信息看,不再有“ply”信息,说明求解过程中只用到了 grp 算法,而没有用到 ply 算法。

第一次 run 命令走了 1040 步,求得一个解,用时约 430 毫秒;第二次 run 命令用了约 265 毫秒得出结论此 quiz 只有一个解,两次 run 命令共走了 1710 步。

退出程序并重新进入交互,这次显式仅用 grp 算法模式求解:

Order please:
bye D:\read\num\Release>sudoku.exe Order please:
mode
Working mode:0 (1:grp-only; 2:ply-only; other:both grp and ply) Order please:
mode 1
Working mode:1 (1:grp-only; 2:ply-only; other:both grp and ply) Order please:
load-quiz s.txt
Quiz loaded. Order please:
run
...
1GW: 8 shrunken out of [2,7]
1022) row 2 incomplete shrunken by group
1023) Guess [1,8] level 9 at 1 out of 2
1026) row 9 complete shrunken by group
1028) col 6 complete shrunken by group
1031) Guess [2,5] level 10 at 1 out of 2
1034) shrinking 4 from [6,3] went wrong
1035) Forward guess [2,5] level 10 at 2 out of 2
812 753 649
943 682 175
675 491 283 154 237 896
369 845 721
287 169 534 521 974 368
438 526 917
796 318 452 Done [steps:1040, solution sum:1].
Run time: 421 milliseconds; steps: 1040, solution sum: 1. Order please:
run
...
1GW: 9 shrunken out of [5,8]
1698) row 5 incomplete shrunken by group
1699) Guess [1,3] level 6 at 1 out of 2
1703) row 1 complete shrunken by group
1705) row 2 complete shrunken by group
1707) row 4 complete shrunken by group
1707) shrinking 9 from blk[5,1] went wrong
1708) Forward guess [1,3] level 6 at 2 out of 2
1709) shrinking 2 from [4,9] went wrong
1710) No more solution (solution sum is 1).
809 000 306
503 600 800
076 090 250 054 007 120
002 045 789
000 100 635 001 000 568
008 500 910
090 000 400 Invalid quiz [steps:1710] - no more solution (solution sum is 1)
Run time: 265 milliseconds; steps: 1710, solution sum: 1. Order please:
bye D:\read\num\Release>

从输出信息看,除了第一次 run 命令用时比之前略微减少(从 430 减为 421)之外,其他信息完全一致。

再看一下显式仅用 ply 算法模式求解的输出信息:

D:\read\num\Release>sudoku.exe

Order please:
load-quiz s.txt
Quiz loaded. Order please:
show
800 000 000
003 600 000
070 090 200 050 007 000
000 045 700
000 100 030 001 000 068
008 500 010
090 000 400 Order please:
mode 2
Working mode:2 (1:grp-only; 2:ply-only; other:both grp and ply) Order please:
run
...
1054) col 6 shrunken ply-1 by vblk 2
[2,8]: 5 7 shrunken to 7 worked by col-ply1.
1056) col 8 shrunken ply-1 by vblk 1
1059) Guess [2,5] level 10 at 1 out of 2
1063) shrinking 8 from [4,7] went wrong
1064) Forward guess [2,5] level 10 at 2 out of 2
812 753 649
943 682 175
675 491 283 154 237 896
369 845 721
287 169 534 521 974 368
438 526 917
796 318 452 Done [steps:1069, solution sum:1].
Run time: 468 milliseconds; steps: 1069, solution sum: 1. Order please:
run
...
1335) col 8 shrunken ply-2 by vblk 2
[4,9]: 1 2 4 6 9 shrunken to 1 4 6 9 worked by col-ply2.
[5,9]: 1 2 6 9 shrunken to 1 6 9 worked by col-ply2.
incomplete shrink met, filter again
1339) Guess [1,3] level 8 at 1 out of 2
...
2100) row 8 shrunken ply-1 by blk 2
[8,2]: 2 3 4 shrunken to 4 worked by row-ply2.
2102) row 8 shrunken ply-2 by blk 3
[6,1]: 2 7 9 shrunken to 7 worked by row-ply2.
[6,3]: 2 4 7 9 shrunken to 4 7 worked by row-ply2.
2104) row 6 shrunken ply-2 by blk 2
2104) shrinking 2 from [8,1] went wrong
2105) No more solution (solution sum is 1).
800 000 306
003 600 800
476 893 251 350 067 100
160 345 700
704 100 635 201 000 568
048 506 910
695 000 400 Invalid quiz [steps:2105] - no more solution (solution sum is 1)
Run time: 493 milliseconds; steps: 2105, solution sum: 1. Order please:

可以看出,仅用 ply 算法求解,比起仅用 grp 算法求解,用时和步数都略有增加。第二次 run 命令的输出里有几次如下的信息输出:

incomplete shrink met, filter again

这正好对应 用C++实现的数独解题程序 SudokuSolver 2.1 及实例分析 里所言的:这样的两次关联收缩,倘若第一次不完全收缩发生在第五轮的 col-ply 筛查阶段,就会导致第二次的完全收缩接续不上,进而多加一次猜测行为。这是一个可改进之处。2.2 版本改进之后一直没有碰到这种情形,直到这里仅用 ply 算法求解时才碰到。

另一道数独题

这一道据说也挺有难度:

005 300 000
800 000 020
070 010 500
400 005 300
010 070 006
003 200 080
060 500 009
004 000 030
000 009 700

把这 9 行数字放到一个文本文件(比如 D:\read\num\Release\s.txt)的头部位置。这次不对输出做删节处理,呈现完整的两次 run 命令输出:

D:\read\num\Release>sudoku.exe

Order please:
load-quiz s.txt
Quiz loaded. Order please:
run
2) row 2 complete shrunken by group
4) row 5 complete shrunken by group
2GW: 2 shrunken out of [4,3]
2GW: 8 shrunken out of [4,3]
2GW: 9 shrunken out of [4,3]
2GW: 5 shrunken out of [6,1]
2GW: 9 shrunken out of [6,1]
CelSet: [4,3] [6,1] ValSet: 6 7
6) blk 4 incomplete shrunken by group
7) Guess [6,2] level 1 at 1 out of 2
8) row 5 complete shrunken by group
11) Guess [4,3] level 2 at 1 out of 2
13) col 3 complete shrunken by group
16) Guess [2,3] level 3 at 1 out of 2
18) Guess [3,3] level 4 at 1 out of 2
24) col 8 complete shrunken by group
28) row 3 complete shrunken by group
30) row 1 complete shrunken by group
32) row 1 complete shrunken by group
35) shrinking 1 from [9,1] went wrong
36) Forward guess [3,3] level 4 at 2 out of 2
2GW: 1 shrunken out of [1,8]
2GW: 4 shrunken out of [1,8]
2GW: 6 shrunken out of [1,8]
2GW: 1 shrunken out of [4,8]
CelSet: [1,8] [4,8] ValSet: 7 9
37) col 8 incomplete shrunken by group
38) Guess [1,1] level 5 at 1 out of 2
40) shrinking 9 from [2,4] went wrong
41) Forward guess [1,1] level 5 at 2 out of 2
43) Guess [1,2] level 6 at 1 out of 2
46) row 2 complete shrunken by group
48) row 3 complete shrunken by group
50) row 4 complete shrunken by group
52) row 4 complete shrunken by group
54) shrinking 8 from [9,4] went wrong
55) Forward guess [1,2] level 6 at 2 out of 2
57) row 3 complete shrunken by group
59) row 8 complete shrunken by group
1GW: 8 shrunken out of [9,4]
1GW: 2 shrunken out of [9,5]
1GW: 8 shrunken out of [9,5]
1GW: 2 shrunken out of [9,9]
1GW: 8 shrunken out of [9,9]
61) row 9 incomplete shrunken by group
62) Guess [1,8] level 7 at 1 out of 2
64) shrinking 9 from [1,5] went wrong
65) Forward guess [1,8] level 7 at 2 out of 2
67) row 2 complete shrunken by group
69) row 4 complete shrunken by group
71) row 6 complete shrunken by group
73) col 4 complete shrunken by group
1GW: 4 shrunken out of [2,9]
75) blk 3 incomplete shrunken by group
76) Guess [1,5] level 8 at 1 out of 2
78) row 1 complete shrunken by group
81) Guess [1,7] level 9 at 1 out of 2
84) Guess [2,6] level 10 at 1 out of 2
87) row 9 complete shrunken by group
89) col 4 complete shrunken by group
92) Guess [4,2] level 11 at 1 out of 2
92) shrinking 8 from [8,7] went wrong
93) Forward guess [4,2] level 11 at 2 out of 2
93) shrinking 5 from [8,1] went wrong
94) Upward guess [2,6] level 10 at 2 out of 2
95) shrinking 5 from [9,9] went wrong
96) Upward guess [1,7] level 9 at 2 out of 2
96) shrinking 4 from blk[6,9] went wrong
97) Upward guess [1,5] level 8 at 2 out of 2
97) shrinking 7 from [2,9] went wrong
98) Upward guess [2,3] level 3 at 2 out of 2
102) row 3 complete shrunken by group
105) Guess [1,9] level 4 at 1 out of 2
106) row 4 complete shrunken by group
108) col 8 complete shrunken by group
2GW: 6 shrunken out of [8,4]
2GW: 8 shrunken out of [8,4]
2GW: 2 shrunken out of [8,6]
2GW: 6 shrunken out of [8,6]
2GW: 8 shrunken out of [8,6]
CelSet: [8,4] [8,6] ValSet: 1 7
110) row 8 incomplete shrunken by group
111) Guess [1,8] level 5 at 1 out of 2
117) shrinking 2 from [4,2] went wrong
118) Forward guess [1,8] level 5 at 2 out of 2
120) shrinking 8 from [9,9] went wrong
121) Upward guess [1,9] level 4 at 2 out of 2
123) Guess [1,7] level 5 at 1 out of 2
124) col 8 complete shrunken by group
2GW: 4 shrunken out of [2,4]
2GW: 1 shrunken out of [8,4]
2GW: 8 shrunken out of [8,4]
CelSet: [2,4] [8,4] ValSet: 6 7
126) col 4 incomplete shrunken by group
127) Guess [1,5] level 6 at 1 out of 2
145 327 698
839 654 127
672 918 543 496 185 372
218 473 956
753 296 481 367 542 819
984 761 235
521 839 764 Done [steps:131, solution sum:1].
Run time: 46 milliseconds; steps: 131, solution sum: 1. Order please:
run
132) Forward guess [1,5] level 6 at 2 out of 2
1GW: 4 shrunken out of [2,6]
135) row 2 incomplete shrunken by group
136) Guess [2,4] level 7 at 1 out of 2
138) row 3 complete shrunken by group
139) shrinking 8 from blk[8,7] went wrong
140) Forward guess [2,4] level 7 at 2 out of 2
142) row 3 complete shrunken by group
143) shrinking 8 from blk[8,7] went wrong
144) Upward guess [1,7] level 5 at 2 out of 2
146) shrinking 8 from [9,4] went wrong
147) Upward guess [4,3] level 2 at 2 out of 2
149) row 6 complete shrunken by group
151) col 8 complete shrunken by group
154) Guess [4,8] level 3 at 1 out of 2
157) row 6 complete shrunken by group
1GW: 4 shrunken out of [1,7]
1GW: 4 shrunken out of [2,7]
159) col 7 incomplete shrunken by group
160) Guess [3,1] level 4 at 1 out of 2
163) shrinking 8 from [9,5] went wrong
164) Forward guess [3,1] level 4 at 2 out of 2
165) row 2 complete shrunken by group
167) row 7 complete shrunken by group
169) row 9 complete shrunken by group
172) Guess [2,2] level 5 at 1 out of 2
174) Guess [1,2] level 6 at 1 out of 2
176) row 3 complete shrunken by group
178) col 6 complete shrunken by group
180) row 5 complete shrunken by group
183) row 8 complete shrunken by group
184) shrinking 2 from [8,7] went wrong
185) Forward guess [1,2] level 6 at 2 out of 2
187) row 2 complete shrunken by group
189) shrinking 5 from [9,1] went wrong
190) Upward guess [2,2] level 5 at 2 out of 2
193) row 1 complete shrunken by group
194) shrinking 6 from [8,6] went wrong
195) Upward guess [4,8] level 3 at 2 out of 2
196) row 6 complete shrunken by group
199) Guess [3,8] level 4 at 1 out of 2
2GW: 1 shrunken out of [1,7]
2GW: 8 shrunken out of [1,7]
2GW: 1 shrunken out of [2,7]
CelSet: [1,7] [2,7] ValSet: 6 9
201) col 7 incomplete shrunken by group
202) Guess [1,9] level 5 at 1 out of 2
203) shrinking 1 from [4,4] went wrong
204) Forward guess [1,9] level 5 at 2 out of 2
206) shrinking 1 from [4,4] went wrong
207) Upward guess [3,8] level 4 at 2 out of 2
208) col 3 complete shrunken by group
210) col 7 complete shrunken by group
212) col 6 complete shrunken by group
214) blk 1 complete shrunken by group
1GW: 1 shrunken out of [7,7]
1GW: 4 shrunken out of [7,7]
1GW: 1 shrunken out of [8,9]
1GW: 1 shrunken out of [9,9]
1GW: 4 shrunken out of [9,9]
216) blk 9 incomplete shrunken by group
217) Guess [1,9] level 5 at 1 out of 2
218) col 2 complete shrunken by group
221) shrinking 9 from [5,3] went wrong
222) Forward guess [1,9] level 5 at 2 out of 2
223) col 7 complete shrunken by group
225) col 7 complete shrunken by group
230) shrinking 8 from [4,4] went wrong
231) Upward guess [6,2] level 1 at 2 out of 2
232) row 6 complete shrunken by group
234) row 5 complete shrunken by group
236) row 6 complete shrunken by group
239) row 8 complete shrunken by group
241) row 9 complete shrunken by group
243) col 3 complete shrunken by group
245) blk 9 complete shrunken by group
248) Guess [1,2] level 2 at 1 out of 2
251) shrinking 7 from [1,9] went wrong
252) Forward guess [1,2] level 2 at 2 out of 2
254) row 3 complete shrunken by group
257) Guess [2,3] level 3 at 1 out of 2
1GW: 2 shrunken out of [9,1]
1GW: 8 shrunken out of [9,4]
1GW: 2 shrunken out of [9,5]
1GW: 8 shrunken out of [9,5]
1GW: 2 shrunken out of [9,9]
1GW: 8 shrunken out of [9,9]
258) row 9 incomplete shrunken by group
259) Guess [1,1] level 4 at 1 out of 2
260) shrinking 6 from [2,4] went wrong
261) Forward guess [1,1] level 4 at 2 out of 2
3GW: 2 shrunken out of [7,5]
3GW: 8 shrunken out of [7,5]
263) col 5 incomplete shrunken by group
264) Guess [2,7] level 5 at 1 out of 2
266) shrinking 2 from [7,7] went wrong
267) Forward guess [2,7] level 5 at 2 out of 2
268) row 1 complete shrunken by group
271) row 1 complete shrunken by group
273) row 5 complete shrunken by group
3GW: shrink went wrong
275) row 7 shrink by group went WRONG
276) Upward guess [2,3] level 3 at 2 out of 2
280) row 5 complete shrunken by group
282) col 7 complete shrunken by group
283) shrinking 6 from [2,4] went wrong
284) No more solution (solution sum is 1).
145 300 900
839 050 127
672 018 543 426 005 371
518 473 296
793 261 485 067 500 819
954 000 632
081 609 750 Invalid quiz [steps:284] - no more solution (solution sum is 1)
Run time: 63 milliseconds; steps: 284, solution sum: 1. Order please:
bye D:\read\num\Release>

可以看到,这个 quiz 的求解过程,出现的最深猜测级别为 11 级:

92) Guess [4,2] level 11 at 1 out of 2

仅比前面那个 quiz 少一级。但从用时和步数看,这个 quiz 要容易不少。

用C++实现的数独解题程序 SudokuSolver 2.4 及实例分析的更多相关文章

  1. 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析

    SudokuSolver 2.3 程序实现 用C++实现的数独解题程序 SudokuSolver 2.2 及实例分析 里新发现了一处可以改进 grp 算法的地方,本次版本实现了对应的改进 grp 算法 ...

  2. 用C++实现的数独解题程序 SudokuSolver 2.2 及实例分析

    SudokuSolver 2.2 程序实现 根据 用C++实现的数独解题程序 SudokuSolver 2.1 及实例分析 里分析,对 2.1 版做了一些改进和尝试. CQuizDealer 类声明部 ...

  3. 用C++实现的数独解题程序 SudokuSolver 2.1 及实例分析

    SudokuSolver 2.1 程序实现 在 2.0 版的基础上,2.1 版在输出信息上做了一些改进,并增加了 runtil <steps> 命令,方便做实例分析. CQuizDeale ...

  4. 用C++实现的数独解题程序 SudokuSolver 2.7 及实例分析

    引言:一个 bug 的发现 在 MobaXterm 上看到有内置的 Sudoku 游戏,于是拿 SudokuSolver 求解,随机出题,一上来是个 medium 级别的题: 073 000 060 ...

  5. 用C++实现的数独解题程序 SudokuSolver 2.6 的新功能及相关分析

    SudokuSolver 2.6 的新功能及相关分析 SudokuSolver 2.6 的命令清单如下: H:\Read\num\Release>sudoku.exe Order please: ...

  6. SudokuSolver 1.0:用C++实现的数独解题程序 【二】

    本篇是 SudokuSolver 1.0:用C++实现的数独解题程序 [一] 的续篇. CQuizDealer::loadQuiz 接口实现 1 CQuizDealer* CQuizDealer::s ...

  7. SudokuSolver 2.0:用C++实现的数独解题程序 【一】

    SudokuSolver 2.0 实现效果 H:\Read\num\Release>sudoku.exe Order please: Sudoku Solver 2.0 2021/10/2 by ...

  8. SudokuSolver 1.0:用C++实现的数独解题程序 【一】

    SudokuSolver 1.0 用法与实现效果 SudokuSolver 是一个提供命令交互的命令行程序,提供的命令清单有: H:\Read\num\Release>sudoku.exe Or ...

  9. 数独GUI程序项目实现

    数独GUI程序项目实现 导语:最近玩上了数独这个游戏,但是找到的几个PC端数独游戏都有点老了...我就想自己做一个数独小游戏,也是一个不错的选择. 前期我在网上简单地查看了一些数独游戏的界面,代码.好 ...

随机推荐

  1. css之px、em、rem

    rem是css3新定义的设置字体大小属性,常用的两种字体大小设置有下面2种:1. px为单位2.em为单位(百分比用法跟em类似) PX为单位 在Web页面初期制作中,我们都是使用"px&q ...

  2. JavaScript高级程序设计(读书笔记)之BOM

    BOM(Browser Object Model)提供了很多对象用于访问浏览器的功能,这些功能与任何网页内容无关. 8.1 window对象 BOM的核心对象是window,它表示一个浏览器实例.在浏 ...

  3. Centos8.3安装broadcom(博通)BCM43142无线网卡驱动,Centos8没有wifi选项(No wifi adapter found centos)解决办法

    参考:杆菌大祭司> https://www.jianshu.com/p/3cb41b7b8fec 第一步:查看网卡型号,确认无线网卡型号为BCMXXX lspci | grep Network ...

  4. leetcode 括号

    1. 括号(0809) 设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合. 说明:解集不能包含重复的子集. 例如,给出 n = 3,生成结果为: [ "((()))" ...

  5. Mybatis-Plus增强包

    简介 本框架(Gitee地址 )结合公司日常业务场景,对Mybatis-Plus 做了进一步的拓展封装,即保留MP原功能,又添加更多有用便捷的功能.具体拓展体现在数据自动填充(类似JPA中的审计).关 ...

  6. 洛谷P1083 借教室 题解

    题目 [NOIP2012 提高组] 借教室 题解 这道题是几周之前做到的一道题,本来不想讲的,因为这道题也是用到了二分答案的方法,这类题目之前已经发布过两篇题解了.但这道题还运用了差分数组这个思想,所 ...

  7. window创建l2tp

    windows上创建一个L2TP的隧道连接 进入控制面板,打开"网络和共享中心",如下图,之后点击"设置新的连接或网络" 进入到"设置连接或网络&qu ...

  8. Elasticsearch(ES)的高级搜索(DSL搜索)(上篇)

    1. 概述 之前聊了一下 Elasticsearch(ES)的基本使用,今天我们聊聊 Elasticsearch(ES)的高级搜索(DSL搜索),由于DSL搜索内容比较多,因此分为两篇文章完成. 2. ...

  9. CDI Features inJavaEE 的上下文和依赖注入

    基本的CDI的功能: 类型安全:CDI使用Java类型来解析注入,而不是通过(字符串)名称注入对象.当类型不足时, 可以使用限定符 注释.这允许编译器轻松检测错误,并提供简单的重构. POJO:几乎每 ...

  10. 微信小程序适配iphoneX的实现方法

    一. 安全区域(safe area) 与iPhone6/6s/7/8相比,iPhone X 无论是在屏幕尺寸.分辨率.甚至是形状上都发生了较大的改变,下面以iPhone 8作为参照物,先看看iPhon ...