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. blender skin modifier 太好玩了

    https://docs.blender.org/manual/en/latest/modeling/modifiers/generate/skin.html 只需要像画火柴人一样把点连起来,skin ...

  2. Vue 2.0 与 Vue 3.0 响应式原理比较

    Vue 2.0 的响应式是基于Object.defineProperty实现的 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 prop ...

  3. rtl8188eu 驱动移植

    测试平台 宿主机平台:Ubuntu 16.04.6 目标机:iMX6ULL 目标机内核:Linux 4.1.15 rtl8188eu 驱动移植 在网上下载Linux版的驱动源码: wifi驱动的实现有 ...

  4. GDB调试:Linux开发人员必备技能

    开篇词:Linux C/C++ 开发人员要熟练掌握 GDB 调试 大家好,我是范蠡,目前在某知名互联网旅游公司基础框架业务部技术专家组任开发经理一职. 本系列课程的主题是 Linux 后台开发的 C/ ...

  5. Docker入门之container篇

    启动 启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容 器重新启动. 因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器. ...

  6. 数据结构(c++)(第二版) Dijkstra最短路径算法 教学示范代码出现重大问题!

    前言 去年在数据结构(c++)的Dijkstra教学算法案例中,发现了一个 bug 导致算法不能正常的运行,出错代码只是4行的for循环迭代代码. 看到那里就觉得有问题,但书中只给了关键代码的部分,其 ...

  7. SpringSecurity-Shiro-初见

    目录 简介 实战环境搭建 SpringSecurity 认证和授权 权限控制和注销 记住我 Shiro 快速上手 shiro整合mybais 简介 在 Web 开发中,安全一直是非常重要的一个方面. ...

  8. MapReduce 示例:减少 Hadoop MapReduce 中的侧连接

    摘要:在排序和reducer 阶段,reduce 侧连接过程会产生巨大的网络I/O 流量,在这个阶段,相同键的值被聚集在一起. 本文分享自华为云社区<MapReduce 示例:减少 Hadoop ...

  9. css3 animate转圈360旋转

    .logo{ width:20px; height: 20px; background: red; -webkit-animation:haha1 .8s linear infinite; anima ...

  10. 搭建http文件服务器 - python3使用http.server搭建http文件服务器

    适用场景 只要有python3就可以,windows系统cmd窗口直接敲命令,Linux系统,直接敲命令 step-1 cd cd 到需要搭建服务器的目录 step-2 http.server pyt ...