2

如何从左到右获取列表的乘积?例如:

?- product([1,2,3,4], P).
P = [1, 2, 6, 24] .

我认为一种方法是重载仿函数并使用 3 个参数:

product([H|T], Lst) :- product(T, H, Lst).

我不知道从这里去哪里。

4

3 回答 3

3

您可以使用此处找到的库(lambda): http : //www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

:- use_module(library(lambda)).
:- use_module(library(clpfd)).


product(L, R) :-
    foldl(\X^Y^Z^(Y = [] 
             -> Z = [X, [X]]
             ;   Y = [M, Lst],
                 T #= X * M,
                 append(Lst, [T], Lst1),
                 Z = [T, Lst1]),
          L, [], [_, R]).

感谢@Mike_Hartl 的建议,代码非常简单:

product([], []).

product([H | T], R) :-
    scanl(\X^Y^Z^( Z #= X * Y), T, H, R).
于 2013-02-28T23:22:30.993 回答
2

看起来像一个列表副本,只是乘以处理的最后一个元素。让我们从最左边的元素 1 开始:

product(L, P) :-
    product(L, 1, P).

product([X|Xs], A, [Y|Ys]) :-
    Y is X * A,
    product(Xs, Y, Ys).
product([], _, []).

如果我们使用库(clpfd):

:- [library(clpfd)].

product([X|Xs], A, [Y|Ys]) :-
    Y #= X * A,
    product(Xs, Y, Ys).
product([], _, []).

它有效(仅适用于整数)“向后”

?- product(L, [1,2,6,24]).
L = [1, 2, 3, 4].
于 2013-02-28T23:06:38.490 回答
1

可能非常肮脏的解决方案(我是 Prolog 的新手):

product([ListHead|ListTail], Answer) :- 
  product_acc(ListTail, [ListHead], Answer).

product_acc([ListHead|ListTail], [AccHead|AccTail], Answer) :-
  Product is ListHead * AccHead,
  append([Product, AccHead], AccTail, TempList),
  product_acc(ListTail, TempList, Answer).

product_acc([], ReversedList, Answer) :- 
  reverse(ReversedList, Answer).
  • 所以基本上在一开始我们调用另一个谓词,它有额外的“变量”Acc,它是累加器列表。

  • 所以我们从原始列表中取出头(第一个数字)并将其放入累加器列表中。

  • 然后我们总是从原始列表中获取头(第一个数字)并将其与累加器列表中的头(第一个数字)相乘。

  • 然后我们必须附加我们通过与累加器的头部相乘然后与尾部相乘得到的新数字

  • 然后我们再次调用相同的谓词,直到原始列表变为空,最后显然我们需要反转它。

它似乎工作

?- product([1,2,3,4], L).
L = [1, 2, 6, 24].

?- product([5], L).
L = [5].

?- product([5,4,3], L).
L = [5, 20, 60].

对不起,如果我的解释不是很清楚。随意发表评论。

于 2013-02-28T22:55:59.917 回答