#prolog #prolog-cut
#пролог #пролог-вырезание
Вопрос:
Я хотел бы получить этот результат:
?- numberMatrixLines(1,[[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]],X).
X = [machinePenalty(1,[1,1,1,1,1,1,1,1]),
machinePenalty(2 [1,1,1,1,1,1,1,1]),
machinePenalty(3,[1,1,1,1,1,1,1,1])]
Я пробую следующий код:
numberMatrixLines(X,[],ResultMatrix):-
writeln('should end here'),
reverse(ResultMatrix,ResultMatrixTemp),
initWith(ResultMatrixTemp,ResultMatrix),
!.
numberMatrixLines(X,[H|T],ResultMatrix):-
append_in_front(machinePenalty(X,H),ResultMatrix,ResultMatrixTemp),
writeln(ResultMatrixTemp),
incr(X,X1),
numberMatrixLines(X1,T,ResultMatrixTemp).
incr(X, X1) :-
X1 is X 1.
append_in_front(X,[],[X]).
append_in_front(X,L1,[X|L1]).
При numberMatrixLines(X,[],ResultMatrix)
достижении результат правильный. ОДНАКО предикат не остановится на этом и не вернет X , как предполагалось.
Что можно сделать, чтобы он остановился в этой строке?
Комментарии:
1. Нет необходимости в
append_in_front/3
предикате.append_in_front(X,T,L)
то же самое, чтоL = [X|T]
.2. И
incr/2
есть почтиsucc/2
, за исключениемsucc/2
того, что работает в обоих направлениях.3. Не видя кода для
initWith/3
, трудно сказать, но если этот предикат завершится неудачей, то все это завершится неудачей. Сокращение не кажется мне полезным, так как если бы первое предложение соответствовало, второе предложение не соответствовало бы, потому что списки не могут быть одновременно пустыми и иметь начало и конец. Я думаю, вы надеетесь, что сокращение сработает как быстрое возвращение. Он этого не делает, он просто привязывает Prolog к тем выборам, которые он уже сделал. Другими словами, сокращения ничего не делают с вашим стеком вызовов, они что-то делают с вашим стеком повторов.
Ответ №1:
Простым решением было бы (я переместил список ввода в первый аргумент, чтобы воспользоваться индексацией первого аргумента Prolog, чтобы избежать ложных точек выбора и необходимости сокращений):
% number_matrix_lines( list, integer, -list)
number_matrix_lines([], _, []).
number_matrix_lines([Line| Lines], I, [machine_penalty(I,Line)| NumberLines]) :-
J is I 1,
number_matrix_lines(Lines, J, NumberLines).
Пример вызова:
| ?- number_matrix_lines([[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]], 1, NumberLines).
NumberLines = [machine_penalty(1,[1,1,1,1,1,1,1,1]), machine_penalty(2,[1,1,1,1,1,1,1,1]), machine_penalty(3,[1,1,1,1,1,1,1,1])]
yes
P.S. Обратите внимание, что в руководствах по кодированию Prolog рекомендуется использовать символы подчеркивания в именах предикатов вместо camelCase.