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. Kubernetes-kubectl介绍

    前言 本篇是Kubernetes第三篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战.本篇重要介绍kubectl的使用. Kubernetes系列文章: Kubernetes介绍 Kuber ...

  2. 洛谷P2424 约数和 题解

    题目 约数和 题解 此题可以说完全就是一道数学题,不难看出这道题所求的是 \(\sum\limits_{i=x}^{y}{\sum\limits_{d|i}{d}}\) 的值. 很显然,用暴力枚举肯定 ...

  3. 代码注释规范之Doxygen

    1.Doxygen简介 Doxygen是一个程序的文档产生工具,可以将程序中的注释转换成说明文档或者说是API参考手册,从而减少程序员整理文档的时间.当然这里程序中的注释需要遵循一定的规则书写,才能让 ...

  4. finally方法体

    1.资源释放 java7可以在try(创建资源对象,方法体结束之后自动释放) 2.finally中有返回

  5. 硕盟SM-T54|type-c转接头HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞接口功能说明

    硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...

  6. 用Java写了一个程序,将一个Mysql库中的表,迁移到另外一个server上的Mysql库中

    用Navicat做数据迁移,因为数据量比较大,迁移过过程中一个是进展不直观,另外就是cpu占用率高的时候,屏幕跟死机了一样点不动按钮,不好中断. 想了想,干脆自己写一个. 在网上找了一个sqllite ...

  7. Java Web下MySQL数据库的增删改查(二)

    前文:https://www.cnblogs.com/Arisf/p/14095002.html 在之前图书管理系统上做了改进优化 图书管理系统v2 首先是项目结构: 1.数据库的连接: 1 pack ...

  8. 利用 uber-go/dig 库管理依赖

    利用 uber-go/dig 库管理依赖 github 地址 官方文档 介绍 dig 库是一个为 go 提供依赖注入 (dependency injection) 的工具包,基于 reflection ...

  9. DS博客作业05--查找

    这个作业属于哪个班级 数据结构--网络2011/2012 这个作业的地址 DS博客作业05--查找 这个作业的目标 学习查找的相关结构 姓名 黄静 目录 0.PTA得分截图 1.本周学习总结 1.1 ...

  10. Python - 生成requirement.text 文件

    前言 该篇操作笔记摘自小菠萝 Python项目中,一般都会有一个 requirements.txt 文件 这个文件主要是用于记录当前项目下的所有依赖包及其精确的版本号,以方便在一个新环境下更快的进行部 ...