Треугольник Паскаля в прологе с рекурсией и без разрезов

#prolog #pascals-triangle

Вопрос:

Я пытаюсь написать программу в прологе, которая возвращает список треугольника Паскаля. Список содержит все элементы строки, указанные при вводе пользователем. Так, например:

 ptriangle(3,X).
 

ВОЗВРАТ:
X = [1, 2, 1]

До сих пор у меня было:

 sumC([X,Y],[Z]) :- Z is X   Y.
sumC([X,Y|L], Z):- H is X   Y,
                    sumC([Y|L],L2),
                    Z = [H|L2].

ptriangle(1,[1]) :- ! .
ptriangle(2,[1,1]) :- !.
ptriangle(N, L) :- Ant is N - 1,
                   ptriangle(Ant,L2),
                   sumC(L2,R),
                   append([1|R],[1],L), !.
 

Но я пытаюсь найти способ сделать это без ! рекурсии и с ее помощью. У вас есть какие-нибудь предложения?

Ответ №1:

Вы уже используете рекурсию в ptriangle . И вы можете избежать сокращения ! за счет некоторого недетерминизма.

Взгляните на это и увидите изменения:

 sumC([X,Y],[Z, 1]) :- Z is X   Y.
sumC([X,Y|L], Z):- H is X   Y,
                   sumC([Y|L],L2),
                   Z = [H|L2].

ptriangle(1,[1]).
ptriangle(2,[1,1]).
ptriangle(N, [1|R]) :- N > 2,
                       Ant is N - 1,
                       ptriangle(Ant,L2),
                       sumC(L2,R).
 

Это append в конце концов может стать дорогостоящим, поэтому вы можете попросить sumC себя дать его, когда будете составлять список.

Попробуйте выяснить, как изменения влияют на выполнение.

пс:

 sumC([X,Y|L], [H|L2]):- H is X   Y,
                        sumC([Y|L],L2).
 

является ли идоматическим способом написания этого:

 sumC([X,Y|L], Z):- H is X   Y,
                   sumC([Y|L],L2),
                   Z = [H|L2].