#prolog
#пролог
Вопрос:
У меня есть предикат min1([4,2,3,5],L). Я хочу, чтобы он возвращал минимальное число для каждого раза, когда список отправляется обратно в виде хвоста. Пример:
List Head|Tail Tail L
[4,2,3,5] [4,2,3,5] [2,3,5] 2
[2,3,5] [2,3,5] [3,5] 2
[3,5] [3,5] [5] 3
[5] [5] [] 5
Мой код:
min([X],[X]).
min([H|T],Min):-
min(T,TMin),
H=<TMin,
Min is H.
min([H|T],Min):-
min(T,TMin),
H>TMin,
Min is TMin.
min1([],[]).
min1([H|T],L):-
min([H|T],R),
write(R),
min1(T,R).
Проблема, с которой я сталкиваюсь, связана с L. Он ничего не печатает. Когда я использую write (R), он показывает мне правильный результат, но я не могу распечатать его в виде списка в L. Что я должен исправить?
?-min1([4,2,3,5],L).
223[5]
L = []
Путем удаления write(R):
?-min1([4,2,3,5],L).
false
Ответ №1:
Одна из ваших проблем заключается в попытке понять вашу программу с помощью ввода-вывода. Часто это не очень полезная вещь в Prolog. Если вас интересуют суффиксы списка, даже просто для отладки, укажите эти суффиксы в качестве аргумента предиката. Это намного понятнее, чем пытаться распечатать промежуточные результаты. Поскольку Пролог выполняет обратные отслеживания, может быть трудно понять, что означает промежуточный результат, в какой момент он существует и можно ли его использовать до того, как при обратном отслеживании он исчезнет.
Ваша другая проблема заключается в попытке сделать слишком много сразу. Выполняйте действия шаг за шагом. Prolog — это язык, который хорошо подходит для разбиения задач на мелкие кусочки. Это также часто заставляет вас разбивать проблему на мелкие кусочки.
Итак, сначала: перечисление суффиксов списка (включая сам список как тривиальный суффикс).
list_suffix(List, List).
list_suffix([_ | Suffix], SuffixOfSuffix) :-
list_suffix(Suffix, SuffixOfSuffix).
?- list_suffix([4, 2, 3, 5], Suffix).
Suffix = [4, 2, 3, 5] ;
Suffix = [2, 3, 5] ;
Suffix = [3, 5] ;
Suffix = [5] ;
Suffix = [].
Затем, отдельно, вычисляем минимум списка. Ваша реализация почти подходит для этого, первое предложение необходимо развернуть [X]
(хотя это могло бы быть более эффективным при использовании аккумулятора):
list_minimum([X], X).
list_minimum([H | T], Min):-
list_minimum(T, TMin),
H =< TMin,
Min is H.
list_minimum([H | T], Min):-
list_minimum(T, TMin),
H > TMin,
Min is TMin.
?- list_minimum([4, 2, 3, 5], Minimum).
Minimum = 2 ;
false.
Теперь, и только сейчас, мы в состоянии решить объединенную проблему:
?- list_suffix([4, 2, 3, 5], Suffix), list_minimum(Suffix, Minimum).
Suffix = [4, 2, 3, 5],
Minimum = 2 ;
Suffix = [2, 3, 5],
Minimum = 2 ;
Suffix = [3, 5],
Minimum = 3 ;
Suffix = [5],
Minimum = 5 ;
false.
Вы можете упаковать это в определение предиката:
list_suffix_suffixminimum(List, Suffix, SuffixMinimum) :-
list_suffix(List, Suffix),
list_minimum(Suffix, SuffixMinimum).
?- list_suffix_suffixminimum([4, 2, 3, 5], Suffix, SuffixMinimum).
Suffix = [4, 2, 3, 5],
SuffixMinimum = 2 ;
Suffix = [2, 3, 5],
SuffixMinimum = 2 ;
Suffix = [3, 5],
SuffixMinimum = 3 ;
Suffix = [5],
SuffixMinimum = 5 ;
false.
Может быть, даже без указания суффикса:
list_suffixminimum(List, SuffixMinimum) :-
list_suffix(List, Suffix),
list_minimum(Suffix, SuffixMinimum).
?- list_suffixminimum([4, 2, 3, 5], SuffixMinimum).
SuffixMinimum = 2 ;
SuffixMinimum = 2 ;
SuffixMinimum = 3 ;
SuffixMinimum = 5 ;
false.
Теперь, и только теперь, когда проблема решена, вы можете добавить ввод-вывод, если хотите. Хотя на данный момент, почему бы и нет?
Комментарии:
1. Спасибо за подробный ответ. Можете ли вы объяснить мне одну маленькую вещь list_suffix(список, список). почему список, список в базовом варианте?
2. Потому что из ваших примеров выглядело так, как будто вы хотели последовательность 2, 2, 3, 5. Вы получаете 2 только дважды, если вы также рассматриваете сам список как его суффикс, поэтому, как только вы вычисляете минимум
[4, 2, 3, 5]
, чтобы получить 2, тогда и минимум[2, 3, 5]
, чтобы получить 2.