2016-05-08 3 views
2

Я пытаюсь создать предикат в Prolog select_integers(X, L), который имеет значение true, если L - это список, содержащий все целые числа в X (X) содержит несколько типов значений).Как выбрать целые числа из списка в Prolog?

Вот что я до сих пор:

select_integers([], []). 
select_integers([X|XS], L) :- 
    integer(X), 
    member(X, L), 
    select_integers(XS, L). 

Что я здесь отсутствует? Как я могу улучшить это, чтобы получить результат, который я хочу? (Он в настоящее время возвращает false за все, что я делаю)

+0

'? - include (integer, YourList, integers) .' – CapelliC

+2

@CapelliC: Неверно получается для' include (integer, [I], []), I = 1.' – false

+0

@false: Я знаю. Но, я думаю, что кто-то, кто * начинает * кодировать в * Prolog *, должен * не * заботиться о. Конечно, это * мое * мнение ... – CapelliC

ответ

0

Думаю, вам нужен другой случай.

case1 для пустого списка.

корпус 2, когда элемент является целым числом добавить его ко второму списку

случай 3, когда элемент не является целым DonT добавить его во втором списке.

select_integers([],[]). 
select_integers([X|XS],[X|L]) :- 
integer(X), 
select_integers(XS,L). 
select_integers([X|XS],L) :- 
\+integer(X), 
select_integers(XS,L). 

Вы можете и можете захотеть изменить его так, что L не имеет дубликатов, если х есть дубликаты. Вы можете сделать это с другим случаем или с отдельным предикатом.

Вы также могли бы сделать его более реляционная, возможно, глядя на REIF вещи, например, в SWI http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/swi/reif.pl, например, запуск может быть:

int_t(X,T):- 
integer(X), 
T = true. 
int_t(X,T):- 
\+integer(X), 
T = false. 

?- tinclude(int_t,[a,b,1,2,3,4,5],X). 
X = [1, 2, 3, 4, 5] . 

Это не полностью реляционная, хотя, как:

?- tinclude(int_t,[A,B],[A,B]). 
false. 

Оба они не являются полными ответами, но могут помочь вам.

+2

Обратите внимание, что 'int_t (X, true), X = 1' неправильно завершается с ошибкой. – false

+2

И поэтому 'select_integers ([X], [X]), X = 1'. Это должно быть либо ошибка создания, либо успех. – false

+3

Здесь быстро и грязно: int_t (X, T): - (integer (X) -> T = true, nonvar (X) -> T = false; freeze (X, int_t (X, T))) .' – repeat

4

Если я загляну в вашу программу, я вижу integer(X), который лучше заменить на when(nonvar(X), integer(X)), поскольку в противном случае он не имеет декларативного значения. Поверь мне.

Но теперь, когда у вас есть чистая программа, мы можем найти ошибки благодаря декларативным свойствам Prolog.

Лучше всего спросить Пролог прямо, что он думает:

?- select_integers(Xs, Ys). 
    Xs = Ys, Ys = [] % expected success 
; *loops* 

Не так много. Цикл не помогает нам. Он просто говорит, что двигатель Пролога попал в бесконечный цикл, несмотря ни на что. Но мы можем специализировать запрос. Как так:

?- Xs = [_], Ys = [_], select_integers(Xs, Ys). 
    false. % unexpected failure 

Может быть, вы бы предпочли вместо Xs = [1], Ys = [1]. Я просто попробовал возможный максимум.

Замечание, что мне пришлось ограничивать как Xs, так и Ys списку с одним элементом. В противном случае цикл запроса.

Ситуация сейчас намного лучше, поскольку неожиданный сбой означает, что мы можем диагностировать программу. В частности, мы можем обобщить программу, удалив некоторые части.Я нашел это обобщение вашей программы:

 
:- initialization((Xs = [_], Ys = [_], select_integers(Xs, Ys))). 
:- op(950, fy, *). 
*_. 

select_integers(_/*[]*/,[]). 
select_integers([X|XS],L) :- 
    *when(nonvar(X), integer(X)), 
    *member(X,L), 
    select_integers(XS,L). 

(Для того, чтобы получить этот фрагмент, я сохранил все в файл, добавил * некоторые цели и сказал make неоднократно (который встроен в SWI и есть this module для SICStus), всегда глядя на сообщение об ошибке, цель которого не удалась. Поэтому я старался как можно больше убрать из вашей программы)

Все, что осталось, несет ответственность за сбой. Все остальное не требуется для возникновения сбоя. Это может быть правильно или неправильно, мы не знаем. На самом деле виновником является L! Если вы посмотрите на правилах чтения его справа налево, он гласит:

условия select_integers(XS,L) верно, то следующим образом (:- призвано символизировать стрелок), что select_integers([X|XS], L) верно.

Другими словами, второй аргумент всегда будет иметь одинаковую длину. И есть только []! Таким образом, вторым аргументом может быть только пустой список.

select_integers([],[]). 
select_integers([X|XS],[X|L]) :- 
    when(nonvar(X), integer(X)), 
    select_integers(XS,L). 

?- Xs = [_], select_integers(Xs, Ys). 
    Xs = Ys, Ys = [_A], 
    when(nonvar(_A), integer(_A)). 
    % missing further answer 

Так что эта программа теперь верна для списков, являющихся целыми числами. Но для списков, которые не являются целыми числами, все равно не получается. Вот краткое исправление для этого:

select_integers([],[]). 
select_integers([X|XS],[X|L]) :- 
    when(nonvar(X), integer(X)), 
    select_integers(XS,L). 
select_integers([X|XS],L) :- 
    when(nonvar(X), \+integer(X)), 
    select_integers(XS,L). 

?- Xs = [_], select_integers(Xs, Ys). 
    Xs = Ys, Ys = [_A], 
    when(nonvar(_A), integer(_A)) 
; Xs = [_A], Ys = [], 
    when(nonvar(_A), \+integer(_A)). 

Есть более сжатые способы выразить это. Как:

integer_t(X, T) :- 
    when(nonvar(X), (integer(X) -> T = true ; T = false)). 

select_integers(Xs, Is) :- 
    tfilter(integer_t, Xs, Is). 

В системе, которая не поддерживает when/2 (ни freeze/2) вы можете быть на безопасной стороне с:

integer_t(X, T) :- 
    functor(X,_,_), 
    (integer(X) -> T = true ; T = false). 

Использование tfilter/3.

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