我昨天和今天都在二郎忙着数独游戏。我现在的工作功能是,我可以检查列表形式的数独,例如。,
[6,7,1,8,2,3,4,9,5,5,4,9,1,7,6,3,2,8,3,2,8,5,4,9,1,6,7,1,3,2,6,5,7,8,4,9,9,8,6,4,1,2,5,7,3,4,5,7,3,9,8,6,1,2,8,9,3,2,6,4,7,5,1,7,1,4,9,3,5,2,8,6,2,6,5,7,8,1,9,3,4].
通过查看约束(正方形、行和列中没有重复项),可以确定是否有效。
这个函数被称为valid(S),它接受一个数独,如果它是有效的数独,则返回true,如果不是,则返回false。该函数忽略用于表示空值的0。这是同一个数独游戏的一个例子,其中有一些随机的空值:
[0,7,1,8,2,3,4,0,5,5,4,9,0,7,6,3,2,8,3,0,8,5,0,9,1,6,7,1,3,2,6,5,7,8,4,9,0,8,6,4,1,2,5,7,0,4,5,7,3,9,8,6,1,0,8,9,3,2,6,4,7,5,1,7,1,4,9,3,0,2,8,6,2,6,5,7,8,1,9,3,4].
下一步是找到列表中的第一个0,并尝试从1到9的值并检查它是否产生有效的数独。如果是这样,我们可以继续到下一个0并尝试那里的值,看看它是否有效。一旦我们不能更进一步,我们就回到前一个0并尝试下一个值等,直到我们最终解决了一个数独。
到目前为止,我的代码是这样的(基于一个几乎可以正常工作的人):
solve(First,Nom,[_|Last]) -> try_values({First,Nom,Last},pos()).
try_values(_,[]) -> {error, "No solution found"};
try_values({First,Nom,Last},[N|Pos]) ->
case valid(First++[N]++Last) of
true ->
case solve({First++[N]},Nom,Last) of
{ok,_} -> {ok, "Result"};
{error,_} -> try_values({First,N,Last},Pos)
end;
false -> try_values({First,N,Last},Pos)
end.
pos()是一个由从1到9的值组成的列表。这个想法是我们为First输入一个空列表,为[_|Last]输入一个数独列表,在其中我们寻找0(Nom?)。然后我们尝试一个值,如果结果的列表根据我们的函数是有效的,我们将继续直到我们失败的位置或有结果。当我们失败时,我们返回一个新的try_values,其中包含我们可能的剩余(Pos)值。
当然,这不起作用,而且会带来回报:
5> sudoku:solve([],0,S).
** exception error: bad argument
in operator ++/2
called as {[6]}
++
[1,1,8,2,3,4,0,5,5,4,9,0,7,6,3,2,8,3,2,8,5,4,9,1,6,7,1,3,2|...]
in call from sudoku:try_values/2 (sudoku.erl, line 140)
in call from sudoku:try_values/2 (sudoku.erl, line 142)
由于我缺乏经验,我无法掌握我需要做什么才能使代码合乎逻辑并工作。如果有经验的人能给我一些建议,我将不胜感激。
try_values([], []) -> error("No solution found");
try_values([Solution], []) -> Solution;
try_values(_, []) -> error("Bad sudoku: multiple solutions");
try_values(Heads, [0|Tail]) ->
NewHeads = case Heads of
[] -> [[P] || P <- pos()];
_ -> [Head++[P] || P <- pos(), Head <- Heads]
end,
ValidHeads = [Head || Head <- NewHeads, valid(Head++Tail)],
try_values(ValidHeads, Tail);
try_values([], [H|Tail]) -> try_values([[H]], Tail);
try_values(Heads, [H|Tail]) -> try_values([Head++[H] || Head <- Heads], Tail).
solve(Board) ->
case valid(Board) of
true -> try_values([], Board);
false -> error("No solution found")
end.
try_values
执行您所描述的操作。它通过遍历Board
构建解决方案,在找到0
时尝试所有可能的解决方案(来自pos()
)并在ValidHead
中收集有效
解决方案以进一步传递它们以继续。因此,它采用了所有可能的方式,如果在某个时候有多个有效
sudoku,它们都将被添加到头
中,并将在以下步骤中对有效
ity进行测试。解决方案
只是调用try_values([], Board)
的包装器。
基本上,在0上递归迭代的方法是跳过所有非零(最后两个
try_值
表达式)并在零上执行工作(第四个try_值
表达式)。
前三个
try_值
表达式检查解决方案是否存在,并在这种情况下返回它。
我正在做一个小的个人数独游戏,并试图扩展它。 到目前为止,我使用递归回溯方法使“Solve”部分正常工作,每当它设法解决递归时,就会返回true。 现在我正在尝试构建一个独特的解决方案板生成器,我在网上找到了很多关于如何实现它的信息。 然而,我在第一步很挣扎,这是我的布尔递归回溯算法变成一个递归算法,它保留了一个可能解决方案的计数。这对于检查我生成的板是否是唯一的至关重要。 更重要的是,我意识到我
主要内容:实用方法递归,重复(复本),列表反转递归是 Erlang 的重要组成部分。首先,让我们通过实现阶乘程序来了解简单的递归。 示例 对于上面的例子,有以下几点需要注意 - 我们首先定义一个函数 fac(N); 我们可以通过定义递归函数 fac(N) 递归; 上面的代码的输出结果是 - 实用方法递归 在本节中,我们将详细了解不同类型的递归及其在 Erlang 中的使用。 长度递归 以递归一个更有效的方法可以用于确定一个列表的长度,现在来看
我正在用Java构建一个数独求解器,我正在使用回溯算法。有一个堆栈溢出错误,我怀疑在我的代码中有无限递归。我知道我提供的信息很少,但我太难了,不知道该怎么做。 网格是一个9乘9的数组,表示每个数独平方,它保存一个名为“value”的自定义类型,该类型简单地包含一个整数和一个布尔值,“IsOriginal”指示该值是给定的还是可更改的。 “moveon”是一个全局变量,它的值在“checkall”中
我对编码还是很陌生的,我正在尝试一些稍微困难的主题,例如修改数独递归回溯程序的解决方案。最初的解决方案是针对大小为3x3的数独,我希望我的解决方案可以与正常大小的数独(9x9)一起使用。3x3解决方案在这里找到。 我觉得我对算法非常了解:对于网格中的每个列表(包含该单元格的可能值),在每一步尝试每个数字,确保电路板仍然有效,移动到下一个列表,分配一个可能的数字直到其有效,等等。如果当前电路板不正确
我需要编写一个递归方法,它需要两个并行数组和单词来查找,查找指定的单词并在另一个数组上每次索引匹配时求和值。例如: 如果我说我需要查找单词,它应该在找到索引时对第二个数组上的值求和。在这种情况下,它应该求和,。 如何使我的递归方法使其采用适当的参数并递归地进行计算。我将使用硬编码值。 这是我目前所拥有的。我很确定我的递归方法需要更多参数,但我会看看是否有人能帮助我
我从迭代函数的角度学习了白盒和黑盒测试。现在我需要对几个递归函数(在F#中)进行白盒和黑盒测试。采用以下gcd递归算法: 对于白盒测试:我该如何准确地覆盖算法的不同分支?天真地说,有两个分支,但当函数被多次调用时,可能的分支将明显增加。我应该使用导致不同数量递归调用的参数进行测试,还是应该确切地确定使用哪些值进行测试? 黑盒:我得到了黑盒测试的一般概念。我们应该看看我们可能想要调用函数的可能值,而