2016-03-20 8 views
0

Я пытаюсь создать небольшую прологическую программу, которая может удалить определенное число из списка, и я не могу заставить его привести к списку.Как сделать результат запроса отображаться в виде списка

Код проходит

delete_all(X,[H|T],Ans):- X\=H ,Ans= H; delete_all(X,T,Ans). 

Когда вход

| ?- delete_all(x,[a,b,x],Answer). 

я

Answer = a ? ; 
Answer = b ? ; 
no 

До сих пор я пытался

| ?- findall(Ans,delete_all(x,[a,b,x],Ans),Ans). 

Который возвращает

Ans = [a,b] 

Да, я хочу этот вывод, но я не хочу, чтобы изменить форму моего запроса. Есть ли другой способ сделать это?

Прошу прощения, если я упускаю из виду основы, действительно новые для этого.

ответ

0

Так как вы сказали, что вы были совершенно новыми для Пролога, я думаю, что это может быть полезно, если мы сначала оценить ваш код, а не только непосредственно предоставляя рабочий образец:

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 

Это должно исправить это :).

+0

это [это] (http://prntscr.com/ahmof4) неправильно? Я продолжаю получать «нет» – Lester

+0

Я отредактировал свой ответ, чтобы попытаться объяснить, почему ваш код еще не работает. Дайте мне знать, если вы заработаете. – SND

+0

проблема с завершением? я продолжал перечитывать, но не понимаю, что я должен менять? вы сказали, чтобы добавить пустой список в конец ответа, но я не знаю, как это сделать ... – Lester

 Смежные вопросы

  • Нет связанных вопросов^_^