我正在做一个需要定义关系nexttri(X,Y)的赋值,使得Y是大于X的最小三角数。
例如
?- nexttri(1,3).
true.
?- nexttri(6,Y).
Y = 10.
我不知道该怎么做。
答案 0 :(得分:1)
此解决方案类似于CapelliC,但会接受三角数最小不等于给定数的情况,从而满足OP的要求定义关系nexttri(X,Y),使得Y是最小三角形数字大于X :
nexttri(X, TriNum) :-
nexttri(X, 1, 1, TriNum).
nexttri(X, TriCnt, TriInc, TriNum) :-
NextCnt is TriCnt + 1,
NextInc is TriInc + NextCnt,
( X < TriInc
-> TriNum = TriInc
; nexttri(X, NextCnt, NextInc, TriNum)
).
?- nexttri(1,1).
false.
?- nexttri(1,3).
true.
?- nexttri(1,4).
false.
?- nexttri(1,6).
false.
?- nexttri(6,Y).
Y = 10.
?- nexttri(9,Y).
Y = 10.
?- nexttri(10,Y).
Y = 15.
答案 1 :(得分:0)
你真的试过什么吗?对于SO来说,显示你的代码几乎是 de rigeur 。
假设这是你所说的“三角数”:http://en.wikipedia.org/wiki/Triangular_number
让我们首先定义一个谓词,它将[理论上]生成一个永无止境的三角数流。由于prolog变量是“一次写入”和本地变量,因此需要使用累加器。因此,一个常见的prolog习惯用法是像这样的公共接口谓词的概念,它只是调用私有工作者谓词。像这样:
triangular_number(X) :- triangular_number(1,X) .
我们使用1对序列进行种子处理。然后,工作者谓词计算等边三角形的三角形数字,其长度为 n ,并将该值与X统一。在回溯时,它会递增< em> n 并递归。像这样:
triangular_number(P,X) :- P > 0 , sum(P,X) .
triangular_number(P,X) :- P > 0 , P1 is P+1 , triangular_number(P1,X) .
当我们回溯到triangular_number / 1时,X与下一个三角数重复统一,给我们永无止境的序列。
这里的worker谓词,triangular_number / 3调用它自己的worker谓词sum / 2,它计算N + N-1 + N-2系列......直到N递减到零,所以sum(3,X) )产生3 + 2 + 1。像这样:
sum(N,X) :- sum(N,0,X) .
sum(0,X,X).
sum(N,T,X) :-
N > 0 ,
N1 is N-1 ,
T1 is T+N ,
sum(N1,T1,X)
.
你是否开始注意到这里的模式?
一旦我们可以生成三角形数字,找出大于特定值的下一个三角形数字很容易:
next_triangular_number(N,X) :-
triangular_number(X) ,
X > N ,
! .
调用triangular_number / 1获取第一个三角形数字(1),将其与指定的边界(N)进行比较,然后成功或失败,仅回溯到triangualar_number / 1,再次使用下一个三角形数字成功。< / p>
轻松!让prolog的推理引擎完成工作。
您是否希望这是确定性的(通过使用剪切!
)取决于您的问题定义。这应该只有一个答案,还是应该继续寻找回溯的解决方案?
答案 2 :(得分:0)
这是一个基于T(0) = 0
和T(n) = T(n-1)+n
的事实的解决方案,在我们的案例中n
未知。只需计算序列,传递假设的T(n-1):
tri_succ(P, T) :- tri_succ(0, 0, P, T).
tri_succ(N, Tn, L, S) :-
N1 is N+1,
Ts is Tn+N1,
( L = Tn
-> S = Ts
; L > Tn
-> tri_succ(N1, Ts, L, S)
).
试验:
25 ?- tri_succ(1,T).
T = 3.
26 ?- tri_succ(6,T).
T = 10.
27 ?- tri_succ(7,T).
false.