level 5
梁东林00
楼主
如下一个程序包函数,用于求解数独的。在.nb和.wl中使用按普通方式或者Compile来打印是确认可行的。但是用来确认的语句是Compile[{}, Do[Print@Grid@#, ##2]] &[array, Sequence @@ circulate][] 会打印所有解。因此,想改成带选项函数,返回第一个解或返回解的个数。 因为有的数度可能有上百万个解。
还是用Compile语句去改写(程序段最后用Which限定的那部分语句,之前调试时,用(**)当作注释括起来了,要使用请去掉)。
但是,去掉(**)进行调试,没有预期效果,也不报错...运算很快结束了,虽然根据不同的选项,返回不同的结果(什么也没返回,或者返回0)。怀疑这部分语句在进入Which的分支后,就又跳出来了,根本没做穷举运算...
BeginPackage["sudokuSolve`"]
sudokuSolve::usage = "sudokuSolve[array]是数独函数";
xSym::usage = "xSym[i]用于产生符号x0i";
Begin["`Private`"]
xSym := Symbol["x" <> IntegerString[#, 10, 2]] &;
Options[sudokuSolve] = {"valueType" -> "firstResult"};(*默认返回第一个数独*)
sudokuSolve[sudoku_List, OptionsPattern[sudokuSolve]] :=
Module[{array, arrayResult, result = 0, cnt = 1, cond, circulate},
array = Map[If[# == 0, xSym[cnt++], #] &, sudoku, {2}];(*0位符号化*)
cond = And @@
Unequal @璐村惂鐢ㄦ埛_053SRMK馃惥Join[array, Transpose@array,
Join @@@ Flatten[Partition[array, {3, 3}], 1]] // LogicalExpand;
(*cond:行与列及九格行化...然后条件化*)
circulate =
Table[{xSym[i + 1],
If[Or @@ Cases[Equal @@@ cond, xSym[i] == _], 0,
Evaluate@If[i < cnt - 1, 9, 1]]}, {i, 0, cnt - 1}];
(*circulate:构造循环条件*)
Which[
OptionValue["valueType"] == "firstResult",(*默认返回第一个数独*)
result =
Module[{count = 0},
Catch[Do[If[MatchQ[
# -> ++count, _ -> 1], Throw[#
]], ##2]]] &[
array, Sequence @@ circulate],
OptionValue["valueType"] == "resultCount",(*选项,返回解的个数*)
result =
Module[{count = 0}, Do[# -> ++count, ##2]; count] &[array,
Sequence @@ circulate]
];
result(*以上部分是能够正确求解数独的,调用函数求解时,速度较慢*)
(*Compile[{},Do[Print@Grid@#,##2]]&[array,Sequence@@
circulate][]如果采用此句Compile,也是能正确执行的,用于显示所有解,以只有一个解为例,
原先上面不加Compile的耗时4.4秒.而这句加了Compile的耗时0.6秒*)
(*再进一步,如下,加Compile的语句是不能按预期执行的,不会报错...在实际调用函数时,按默认选项,很快运算结束,
什么也没有返回...按"resultCount"选项,调用函数时,很快运算结束,返回0......怀疑根本就没有执行这部分内部的穷举运算
Which[
OptionValue["valueType"]\[Equal]"firstResult",
result=Compile[{},Module[{count=0},Catch[Do[If[
MatchQ[#\[Rule] ++count,_\[Rule] 1],Throw[#]],##2]]]]&[array,
Sequence@@circulate][],
OptionValue["valueType"]\[Equal]"resultCount",
result=Compile[{},Module[{count=0},Do[#\[Rule] ++count,##2];
count]]&[array,Sequence@@circulate][]
];
result*)
]
End[]
EndPackage[]
2023年09月27日 01点09分
1
还是用Compile语句去改写(程序段最后用Which限定的那部分语句,之前调试时,用(**)当作注释括起来了,要使用请去掉)。
但是,去掉(**)进行调试,没有预期效果,也不报错...运算很快结束了,虽然根据不同的选项,返回不同的结果(什么也没返回,或者返回0)。怀疑这部分语句在进入Which的分支后,就又跳出来了,根本没做穷举运算...
BeginPackage["sudokuSolve`"]
sudokuSolve::usage = "sudokuSolve[array]是数独函数";
xSym::usage = "xSym[i]用于产生符号x0i";
Begin["`Private`"]
xSym := Symbol["x" <> IntegerString[#, 10, 2]] &;
Options[sudokuSolve] = {"valueType" -> "firstResult"};(*默认返回第一个数独*)
sudokuSolve[sudoku_List, OptionsPattern[sudokuSolve]] :=
Module[{array, arrayResult, result = 0, cnt = 1, cond, circulate},
array = Map[If[# == 0, xSym[cnt++], #] &, sudoku, {2}];(*0位符号化*)
cond = And @@
Unequal @璐村惂鐢ㄦ埛_053SRMK馃惥Join[array, Transpose@array,
Join @@@ Flatten[Partition[array, {3, 3}], 1]] // LogicalExpand;
(*cond:行与列及九格行化...然后条件化*)
circulate =
Table[{xSym[i + 1],
If[Or @@ Cases[Equal @@@ cond, xSym[i] == _], 0,
Evaluate@If[i < cnt - 1, 9, 1]]}, {i, 0, cnt - 1}];
(*circulate:构造循环条件*)
Which[
OptionValue["valueType"] == "firstResult",(*默认返回第一个数独*)
result =
Module[{count = 0},
Catch[Do[If[MatchQ[
# -> ++count, _ -> 1], Throw[#
]], ##2]]] &[
array, Sequence @@ circulate],
OptionValue["valueType"] == "resultCount",(*选项,返回解的个数*)
result =
Module[{count = 0}, Do[# -> ++count, ##2]; count] &[array,
Sequence @@ circulate]
];
result(*以上部分是能够正确求解数独的,调用函数求解时,速度较慢*)
(*Compile[{},Do[Print@Grid@#,##2]]&[array,Sequence@@
circulate][]如果采用此句Compile,也是能正确执行的,用于显示所有解,以只有一个解为例,
原先上面不加Compile的耗时4.4秒.而这句加了Compile的耗时0.6秒*)
(*再进一步,如下,加Compile的语句是不能按预期执行的,不会报错...在实际调用函数时,按默认选项,很快运算结束,
什么也没有返回...按"resultCount"选项,调用函数时,很快运算结束,返回0......怀疑根本就没有执行这部分内部的穷举运算
Which[
OptionValue["valueType"]\[Equal]"firstResult",
result=Compile[{},Module[{count=0},Catch[Do[If[
MatchQ[#\[Rule] ++count,_\[Rule] 1],Throw[#]],##2]]]]&[array,
Sequence@@circulate][],
OptionValue["valueType"]\[Equal]"resultCount",
result=Compile[{},Module[{count=0},Do[#\[Rule] ++count,##2];
count]]&[array,Sequence@@circulate][]
];
result*)
]
End[]
EndPackage[]