Так как вы сказали, что вы были совершенно новыми для Пролога, я думаю, что это может быть полезно, если мы сначала оценить ваш код, а не только непосредственно предоставляя рабочий образец:
delete_all(X,[H|T],Ans):-
X \= H, Ans = H ;
delete_all(X,T,Ans).
В словах, это говорит:
X не равен H, если да, то объединить Ans с Н
ИЛИ
рекурсивно сделать то же самое для хвоста
Это объясняет, почему ваша программа дает отдельные результаты, когда элемент не был равен X и возвращает ложь, когда тот или иной элемент встречается в списке. Чтобы объяснить немного дальше, почему вы получаете ложное в последнем случае, давайте рассмотрим 2 небольшие примеры исполнения:
delete_all(e,[a,e],Ans)
CASE e \= a -> Ans = e (Prolog returns you Ans)
delete_all(a,[a],Ans)
CASE a = a -> the OR operator triggers and recursion starts
Но упс, мы теперь войти в этот сценарий:
delete_all(a,[],Ans)
На данный момент, Prolog не соответствует ни одному из ваших кодов, потому что список пуст, и вы нигде не указываете его. Вы видите и понимаете, что происходит (и идет не так)?
Теперь, когда мы оценили ваш код, давайте попробуем написать модель, в которой мы можем выразить то, что вы пытаетесь выполнить.Это всегда хорошая идея, чтобы разбить любую проблему на более мелкие куски, так что давайте начнем:
Мы можем попытаться удалить что-нибудь в пустом списке -> это всегда должно быть истинным
Мы можем попробуйте удалить что-то в непустом списке, но мы хотим получить фактический итоговый Список, который будет возвращен, а не удаленный элемент. Для этого нам нужно будет отслеживать каждый элемент, который не нуждается в удалении во время рекурсии, и просто пропустить элементы, которые мы хотели бы удалить.
Мы начнем с базового случая:
% Base case for empty list (_ = wildcard, since we do not care about
% which element we want to delete out of an empty list)
delete_all(_,[],[]).
Теперь, за исключением случаев, в которых мы должны обрабатывать элементы:
% X is not equal to H, so we want to preserve H in our result list
delete_all(X,[H|T],[H|Ans]) :-
...
...
% X is equal to H, so we want to skip H and not add it to our result list
delete_all(X,[H|T],Ans) :-
...
...
Как вы можете видеть, мы теперь имеют очень легкую для чтения и структурированную модель для вашей проблемы. Все, что осталось сейчас, это написать фактические условия и рекурсивные вызовы. Я подумал, что это может быть хорошей идеей для вас, чтобы попытаться написать их сами, так как это лучший способ узнать!
Кроме того, не пожалеете, каждый должен где-то начать, вот почему все здесь, чтобы помочь. Дайте мне знать, если вы заработаете, если нет, я отредактирую этот пост, чтобы указать дополнительную информацию.
Удачи вам!
EDIT
Вы очень близко, это просто оставляет последний бит объяснения. Рассмотрим следующий пример:
% Prepend H to our current result being built recursively
recursion([H|T],[H|Result]):-
recursion(T,Result). % Call recursively with the result tail
Так что это делает держать предваряя каждый H перед нашим результатом, а затем сделать фактический рекурсивный вызов с нашим результатом хвоста. Это как думать в обратном направлении.
Давайте разбить его:
recursion([a,b,c],Result)
% Execution:
(1) case H = a : prepend a to result and call recursively with result tail
(2) case H = b : prepend b to result and call recursively with result tail
(3) case H = c : prepend c to result and call recursively with result tail
Теперь мы достигнем точки, где наш список ввода становится пустым, и это объясняет, почему мы должны наш базовый случай:
recursion([],[]).
Этот случай говорит: всякий раз, когда наш входной список пуст, мы собираемся добавить пустой список, чтобы получить желаемый результат. Если вы задаетесь вопросом, почему пустой список, то есть только как работает Пролог:
[a,b,c] is equivalent to [a,b,c|[]]
Вы можете прочитать некоторые больше об этом на this и this вопрос.
Итак, чтобы подвести итог (и до сих пор не даем явно ответа :)), вы правильно написали условия, также присутствует базовый случай, проблема заключается в том, как вы делаете свой рекурсивный вызов. Вы можете понять это? Держи меня в курсе!
EDIT
Разница между попыткой и рабочим раствором является рекурсивным вызовом вы делаете. Если вы делаете:
recursion([H|T],R) :-
recursion(T,[H|R])
Вы будете в конечном итоге с обратным списком, потому что вы делаете рекурсивный вызов Предварение H к R, который является не то, что мы хотим в этом случае. Вот почему мы указываем префикс в голове delete_all и - и поэтому ваш код не работает - вызывается рекурсивно только с результатом. Вот почему мы пишем базовый случай с пустым списком. Я дам вам быстрый пример:
% We prepend H to our result in the recursive call
recursion([],R) :- write('Ended with result: '), writeln(R).
recursion([H|T],R) :-
recursion(T,[H|R]). % <- here
Выходы:
?- recursion([1,2,3],R).
Ended with result:
[3, 2, 1|_G5835] % <- note the uninstantiated var and reversed order
Правильный пример:
% We prepend H to our result in the head of recursion2
recursion2([],[]).
recursion2([H|T],[H|R]) :- % <- here
recursion2(T,R). % and recursive call with just R
Это выходы:
?- recursion2([1,2,3],R).
R = [1, 2, 3]
Так что вам нужно только отредактируйте свои рекурсивные вызовы, а не prependi ng H к вашему результату, сделайте это в своей голове и просто передайте свой Ans var в рекурсивном вызове.
% We prepend H to Ans in the head of delete_all
delete_all(X,[H|T],[H|Ans]) :-
...
delete_all(X,T,Ans). % <- and make the recursive call with just Ans
Это должно исправить это :).
это [это] (http://prntscr.com/ahmof4) неправильно? Я продолжаю получать «нет» – Lester
Я отредактировал свой ответ, чтобы попытаться объяснить, почему ваш код еще не работает. Дайте мне знать, если вы заработаете. – SND
проблема с завершением? я продолжал перечитывать, но не понимаю, что я должен менять? вы сказали, чтобы добавить пустой список в конец ответа, но я не знаю, как это сделать ... – Lester