Вчера и сегодня я был занят решателем судоку в Erlang. Рабочая функциональность, которая у меня есть сейчас, заключается в том, что я могу проверить, есть ли судоку в виде списка, например,
[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), которая принимает судоку 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)
По своей неопытности я не могу понять, что мне нужно сделать, чтобы код стал логичным и работал. Я был бы очень признателен, если бы кто-то с большим опытом мог дать мне несколько советов.
solve({First++[N]},Nom,Last)
, насколько я могу судить,solve
ожидает, чтоFirst
будет списком, тогда вы, вероятно, имели в видуsolve(First++[N],Nom,Last)
- person zaquest   schedule 04.10.2013