Рекурсивность | Натуральные числа в прологе списка

у меня следующая проблема, "вернуть числа натуральных чисел массива"

бывший. натуральные(R,[6,-7,-4,3,2,8]). Р = 4

когда появляются отрицательные числа, возвращайте false и ломайте мою рекурсивность

naturales(R,[Head|Tail]):-naturales(R1,Tail), Head >= 0, R is R1+1.
naturales(0,[]).

person Frank Toledo    schedule 02.10.2019    source источник


Ответы (4)


Вот очень короткое решение:

naturales(In, Out) :-
    aggregate(count,X^(member(X, In), X >= 0), Out).
person joel76    schedule 03.10.2019

Если вашему предикату действительно нужно иметь только 2 аргумента, один из которых является результатом, R, а другой — заданным списком, [H|T], вы можете сделать что-то вроде этого. Обратите внимание, что первый предикат вызывает второй «натуральный» с 3 аргументами, а затем этот предикат запускает рекурсивный процесс. C — это всего лишь счетчик, к которому вы можете добавить количество положительных элементов, а затем скопировать это значение в результат в последней строке кода. Первая строка предназначена только для того, чтобы убедиться, что пустой список возвращает 0 положительных элементов. Вероятно, есть лучшие способы сделать это, этот, вероятно, самый интуитивный.

naturales(X, []):- X = 0.
naturales(R, [H|T]):- naturales(R, [H|T], 0).

naturales(R, [H|T], C):- (H > 0, C1 is C + 1, naturales(R1, T, C1), R = R1) ; naturales(R1, T, C), R = R1.
naturales(X, [], X).
person Diogo Soares    schedule 02.10.2019

Распространенной идиомой пролога является использование вспомогательного предиката с переменной-аккумулятором (дополнительной). Попробуйте что-то вроде этого:

natural_numbers( Xs, N ) :- natural_numbers( Xs, 0, N ).

natural_numbers( []     , N , N ) .
natural_numbers( [X|Xs] , T , N ) :-
  ( X > 0 -> T1 is T+1 ; T1 = T ) ,
  natural_numbers( Xs, T1, N ).
person Nicholas Carey    schedule 02.10.2019

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

naturales(R,[Head|Tail]):-naturales(R1,Tail), (Head >= 0, R is R1+1 ; R=R1).
naturales(0,[]).

Теперь почти каждый Prolog (кроме mine :) реализует (->)/2, также знает как «если-то-иначе». Таким образом, патч также может быть написан как

naturales(R,[Head|Tail]):-naturales(R1,Tail), (Head >= 0 -> R is R1+1 ; R=R1).
naturales(0,[]).

Учитывая, что naturales/2 в любом случае не является хвостовой рекурсией (см. Ответ @NicholasCarey для этого), я думаю, что это не имеет для вас практического значения.

person CapelliC    schedule 03.10.2019