Prolog 中的算术 - 数字的倍数

Arithmetic in Prolog - Multiples of a number

我想创建一个函数 multiples(X, N, R),其中 R 是一个列表,其中包含从 XX * N 的所有 X 的倍数。

一个例子是:multiples(3, 4, [12, 9, 6, 3]),它应该给出 true。

到目前为止我的代码:

multiples(X, N, R) :- X >= 1, N >= 1, Z is X*N, contains(Z, R).

contains(Z, [Z|_]).
contains(Z, [W|V]) :- contains(Z,V), L is Z-X, L >= X, contains(L, V).

multiples(3,4,X). 的控制台输出是 X = [12|_xxxx],当我键入 ; 时发生错误。
我如何设法收到我想要的列表?
(也许我的想法是完全错误的)。

对您的代码稍作修改。 contains predicate会收集一个列表中的数字,N会不断递减,直到满足基本谓词。

multiples(X, N, R) :- X >= 1, N >= 1, contains(X,N, R),!.

contains(_,0,[]).
contains(X,N,[Z|List]):-
    Z is X*N,
    N1 is N-1,
    contains(X,N1,List).

示例:

?- multiples(3,4,R).
R = [12, 9, 6, 3]

?- multiples(2,5,R).
R = [10, 8, 6, 4, 2]

?- multiples(25,5,R).
R = [125, 100, 75, 50, 25]

我发现您的代码有 4 个问题。这是固定代码,解释如下:

multiples(X, N, R) :- 
    X >= 1, 
    N >= 1, 
    Z is X*N, 
    contains(X, Z, R).

contains(X, Z, [Z|V]) :- 
    L is Z-X, 
    L >= X, 
    contains(X, L, V).
contains(_, Z, [Z]).

?- multiples(3,4,X).
X = [12, 9, 6, 3] ;
X = [12, 9, 6] ;
X = [12, 9] ;
X = [12] ;
false.

首先,在您的 contains 谓词中,您访问 XW 并且从不声明它们的值。通过向谓词添加另一个属性来解决 X。通过将其替换为 Z.

来解决 W

另一个问题是规则的顺序。较大的 contains 规则应该是“主要”规则,只有当这个规则失败时,另一个才应该“触发”。通过将默认规则置于顶部,您将获得正确的结果。

规则 contains(_, Z, [Z]). 也标记结束,因此 return 列表中只有元素 Z,不包含任何其他(未知)元素。

最后一点是您不需要在 contains 主规则中调用两次 contains

该示例适用于第一个答案。但是,您可以通过剪切 (!) 来改进这一点,这会阻止在成功访问第一条规则后转到第二条规则:

contains(X, Z, [Z|V]) :- 
    L is Z-X, 
    L >= X, 
    !,
    contains(X, L, V).
contains(_, Z, [Z]).

?- multiples(3,4,X).
X = [12, 9, 6, 3].