我目前正在Prolog中制作一个程序,它将计算一个数字的所有倍数(包括其自身),不超过另一个数字的值。我正在测试下面的查询:
?- multiples(4,12,R,0)
此查询将列出小于或等于12的所有4的倍数,例如。 R将返回结果,0表示我打算实现一个计数器,该计数器将计算每次乘法,例如。 4 * 1,4 * 2,4 * 3。我被卡住了,我不确定是否更好的设计是简单地添加倍数并检查它是否低于上限或者是否可以使用计数器或累加器完成。
multiples(N,U,R,Ctr) :-
N =< U,
R is Ctr * N,
R =< U,
increment(Ctr,Ctr2),
multiples(N,U,R,Ctr2).
increment(Num, Num1) :-
Num1 is Num+1.
我相信我的程序在从内部调用倍数的递归步骤失败了。我知道递归需要一个基本案例来允许它退出,但我完全被困在这里并且会欣赏一些方向。
答案 0 :(得分:1)
你遇到的问题是没有基础:你的算法确实会产生false.
它会R
与N
统一,然后做递归和递归将尝试将R
与2*N
统一,但这将失败。
一个想法可能是使用累加器每次添加增量。类似的东西:
multiples(N,U,R) :-
multiples(N,N,U,R).
multiples(_,C,U,C) :-
C =< U.
multiples(N,C,U,R) :-
C =< U,
C1 is C+N,
multiples(N,C1,U,R).
所以我们在这里打电话给multiples(3,12,R).
,结果是:
?- multiples(4,12,R).
R = 4 ;
R = 8 ;
R = 12 ;
false.
答案 1 :(得分:1)
CLP(FD)在这里非常有帮助:
:- use_module(library(clpfd)).
multiple(Multiplicand, Max, Multiple) :-
MaxMultiplier #= Max // Multiplicand,
label([MaxMultiplier]),
Multiplier in 1 .. MaxMultiplier,
Multiple #= Multiplier * Multiplicand,
label([Multiple]).
?- multiple(4, 12, M).
M = 4 ;
M = 8 ;
M = 12.
?-
在这种情况下使用CLP(FD),您还可以使用第一个参数作为变量进行查询:
|?- multiple(N, 12, 8).
N = 8 ;
N = 4 ;
N = 2 ;
N = 1.
或者乘数和结果:
?- multiple(N, 4, M).
N = M, M = 3 ;
N = M, M = 4 ;
N = M, M = 2 ;
N = 2,
M = 4 ;
N = M, M = 1 ;
N = 1,
M = 2 ;
N = 1,
M = 3 ;
N = 1,
M = 4.
?-
如果您想在列表中收集它们,可以使用findall/3
:
?- findall(Multiple, multiple(4, 12, Multiple), Multiples).
Multiples = [4, 8, 12].
?-