gpt4 book ai didi

prolog - 强制变量重新分配(Prolog)

转载 作者:行者123 更新时间:2023-12-03 21:47:16 25 4
gpt4 key购买 nike

作业是接受两个变量,一个 0 到 10,000 之间的数字,以及 1 到该数字之间有多少个循环素数。

我在通过递归将变量传回时遇到问题(我认为回溯就是所谓的。)我得到了正确的数字,我很确定我已经理解了这个概念,我遇到的问题是当我尝试重新分配一个变量时它会抛出一个错误 (?!)

代码如下:

circPrimeCompare(Below, NumCirc):-
RealNum is 0,
circPrimeCompare(1, Below, RealNum, []),
print('R: '),
print(RealNum),
nl,
(NumCirc =:= RealNum).

circPrimeCompare(_, 0, _, _).
circPrimeCompare(N, 1, _, _):- prime(N), print('aaa').
circPrimeCompare(X, Below, RealNum, L):-
( prime(X), X<Below ->
print(X),
nl,
numDigits(X, Y),
rotate(X, Y, N2),
( prime(N2)
-> RealNum2 is RealNum + 1
; RealNum2 is RealNum
),
X2 is X + 1,
( not(circPrimeCompare(X2, Below, RealNum2, L))
-> RealNum = RealNum2, print(RealNum), nl
; RealNum = RealNum2, print(RealNum), nl
),
print('RealNum2: '),
print(RealNum),
nl
;
( X<Below ->
X2 is X + 1,
RealNumPass is RealNum,
( not(circPrimeCompare(X2, Below, RealNumPass, L))
-> RealNum = RealNumPass, print(RealNum), nl
; RealNum = RealNumPass, print(RealNum), nl
),
print('RealNum: '),
print(RealNum),
nl
)
).

这是痕迹:

   Fail: (26) circPrimeCompare(10, 10, 4, []) ? creep
^ Exit: (25) not(user:circPrimeCompare(10, 10, 4, [])) ? creep
Call: (25) 4=4 ? creep
Exit: (25) 4=4 ? creep
...
Exit: (24) circPrimeCompare(9, 10, 4, []) ? creep
^ Fail: (23) not(user:circPrimeCompare(9, 10, 4, [])) ? creep
Call: (23) 4=4 ? creep
Exit: (23) 4=4 ? creep
...
Exit: (22) circPrimeCompare(8, 10, 4, []) ? creep
^ Fail: (21) not(user:circPrimeCompare(8, 10, 4, [])) ? creep
**Call: (21) 3=4 ? creep
Fail: (21) 3=4 ? creep**
Redo: (21) numDigits(7, _G589) ? creep

粗体部分是让我感到困惑的地方。我真的不明白为什么它会这样。是因为变量本质上只有一种用途吗?关于如何修复它的任何想法?

(是的,我意识到这是非常非常糟糕的代码。在这次作业之前我从来没有用 Prolog 写过任何东西。)

最佳答案

您没有以“Prolog”方式思考问题。特别是尝试“重新分配”一个变量不是 Prolog 的方式。变量在满足目标和子目标的过程中被绑定(bind),而不是重新分配一个值,我们经常安排代码携带一个“累加器”变量,只在计算的最后阶段将它的值传递给另一个“最终”变量.

回溯和递归是不同的东西。回溯发生在目标(或子目标)失败时,Prolog“引擎”试图以不同的方式满足该目标。如果我们用尽不同的规则等来满足目标,那么它就会失败。 (这可能会导致 Prolog 引擎回溯到先前的子目标并尝试以不同的方式满足那个。)

递归是指谓词是根据自身定义的,即如果调用谓词会导致同一谓词作为子目标再次调用。

要在 Prolog 中完成许多任务,我们必须从递归而不是迭代的角度来考虑它们,这在过程语言中很自然。这就是我们求助于“累加器”变量的原因,这些变量在不习惯的人看来是谓词中额外的和可能不必要的参数。

但是,一旦您看到了这个想法的实际应用,您可能会因为能够以新的方式应用这个概念而获得一定程度的满足感。

让我们将给定列表中的数字相加作为模型问题。天真的方法是写:

sum(List,Sum).

List 是一个数字列表,Sum 应该是我们的输出,包含列表中规定的值的总和。

基本思路很自然,你考虑列表的HeadTail,如果列表(还)不为空,你想“重新分配” "Sum = Sum + Head,然后递归地处理 Tail(直到列表为空并且我们有我们想要的 Sum)。

但这在 Prolog 中没有意义,因为您不能像过程语言所允许的那样更改 Sum 的值。这是将累加器参数添加到我们的谓词并执行相同工作的地方,但以 Prolog 喜欢的方式。

sumAux([ ],Sum,Sum).
sumAux([H|T],Accum,Sum) :-
NewAccum is Accum + H,
sumAux(T,NewAccum,Sum).

sum(List,Sum) :- sumAux(List,0,Sum).

这里我们引入了一个“辅助”谓词 sumAux/3 和一个额外的参数,我们通过设置根据该谓词定义了 sum/2 “累加器”中间参数为零,但同时传递 ListSum 参数。

稍微思考一下它是如何工作的将会返回你的努力,我希望你很快就会以各种新颖的方式应用这个范例(例如计算循环素数)。

关于prolog - 强制变量重新分配(Prolog),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16282034/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com