Новичок в Prolog - обратный список вывода

Я новичок в Prolog и ищу способ изменить вывод этого кода.

fib(N, F) :- fib(N, 0, [1], F).
fib(0, _, A, A).
fib(N, A, [B|Bs], F) :- N1 is N - 1, Sum is A + B, fib(N1, B, [Sum,B|Bs], F).

Код вычисляет числа Фибоначчи для значения N и печатает результат в виде F.

Например, fib(4,X). производит X=[5,3,2,1,1]. Я хочу X=[1,1,2,3,5] (обратный вывод).

Кажется, я не могу привести его к этому формату и сохранить свойство хвостовой рекурсии.

спасибо за любую помощь


person Frank F    schedule 14.12.2014    source источник


Ответы (1)


Если вы просто хотите перевернуть список в конце, используйте reverse/2:

fib(N, F) :- fib(N, 0, [1], FRev), reverse(FRev, F).

Если вы хотите построить список в обратном порядке, вам придется переосмыслить предложения. Одним из решений является использование last/2 и append/3 для помещения новых элементов в конец аккумулятора, а не перед ним.


После возврата первого решения Пролог пытается найти второе, и вы, вероятно, получите ошибку:

?- fib(5, F).
F = [8, 5, 3, 2, 1, 1] ;
ERROR: Out of global stack

Это происходит потому, что для цели fib(0, ...) Пролог использует первое правило, но создает точку выбора и возвращается к ней позже. С этого момента стек заполняется целями: fib(-1,...), fib(-2,...) и т. д. Ни одна из них никогда не будет достигнута. Вы должны поместить оператор cut в первое предложение для fib/4:

fib(0, _, A, A):-!.

поэтому он не будет пытаться повторно удовлетворить fib(0,...), используя второе правило.

?- fib(5, F).
F = [8, 5, 3, 2, 1, 1].
person Tudor Berariu    schedule 14.12.2014