所以我遇到了Prolog问题。让我们说你要求:
?-num(100,200).
程序应该从这个间隔返回所有数字,这个数字可以从减少theosophique生成数字6(123 = 1 + 2 + 3 = 6所以我应该返回123,105 = 1 + 0 + 5 = 6所以我应该我也已经有了计算这个程序的程序。我有一些东西,我很确定我应该工作,但它甚至可以运行。这就是我到目前为止所得到的还原效果非常好
num(X,Y):-
repeat,
reduct(X,T),
T=:=6 ->write(X),
X is X+1,
(X=:=Y),!.
答案 0 :(得分:2)
除了CapelliC建议使用between/3
(这是在这种情况下迭代一系列整数的理想选择)之外,让我们分解你现有的谓词以查看错误。
注意运营商优先级
','高于->
。所以你的谓词就像这样:
num(X,Y):-
repeat,
reduct(X,T),
T=:=6 ->
( write(X),
X is X+1,
(X=:=Y), !
).
只要T =:= 6
失败,您就会有一个无限循环,repeat, reduct(X, T), T =:= 6
因为X
永远不会改变,因此T
永远不会改变,所以{{ 1}}继续失败并且Prolog 回溯到T =:= 6
。那么,在你的代码中,这是一个无限循环。
您使用repeat
和剪切(repeat
)的策略在此处不起作用
在形式上,你拥有的是:
!
repeat,
<do some queries>,
X =:= Y, % succeed if X and Y have the same value
!
总是成功的。任何时候Prolog都会回溯到repeat
,然后它会继续向前寻找更多解决方案。剪辑告诉Prolog在该点之前不要回溯(切割点)。这里的问题是repeat
,它已经从X
查询调用开始实例化(到100),永远不会与设置为200的num(100, 200)
具有相同的值(见下文)。所以Y
总会失败。
在Prolog谓词子句中,除了通过回溯和重新统一之外,不能更改变量
当您查询X =:= Y
时,从num(100, 200)
和X
开始分别使用100和200进行实例化。此时,Y
和X
的值现在从不在谓词子句执行过程中发生变化。表达式Y
将始终失败,因为Prolog将评估X is X + 1
并确定是 X + 1
,这是永远不会成立的(在这种情况下,它总是将100与101)进行比较。
当您在Prolog中查询谓词时,请说X
,它会查找尚未设置的任何变量(它们是未实例化)的值,这些变量使查询< EM>真。如果找到这样的值,它就会成功。如果找不到,则失败。如果您有一系列由连词(foo(A, B)
)分隔的查询,例如,
,则Prolog首先查询foo1(A), foo2(A)
,如果成功,则会查询foo1(A)
。如果foo2(A)
失败,则Prolog将回溯至foo2(A)
并尝试使用foo1(A)
*的其他值使其成为真,如果A
未实例化(未设置)A
之前。
迭代整数范围
在您的作业中,您需要在foo1(A)
查询中从一个整数迭代到另一个整数(从X
到Y
。如何在没有回溯的情况下使用Prolog中无法重新分配变量的限制来完成这项工作?在Prolog中有不止一种方法可以做到这一点。一个干净的方法是CapelliC使用num(X, Y)
显示的方法。
between/3
另一种方式是递归:
num(X, Y) :-
% `between` will first instantiate N with X.
% On backtracking, it will instantiate N with successive values
% and succeed until the value exceeds Y. Then it will fail.
%
between(X, Y, N),
<do some calls with N, write out successful values>,
fail. % Automatically backtrack here
递归将持续到num(X, Y) :-
% NOTE: if X and Y are given, then their values CANNOT BE CHANGED
% in this predicate clause!
%
X =< Y, % num(X, Y) succeeds only if X =< Y
<do some calls with X and/or Y, write successful values>,
NextX is X + 1, % New variable whose value is X + 1
num(NextX, Y).
看到num
大于X
并最终失败。
Prolog“if-else”构建
如果要执行Y
构造,则需要使用括号来将运算符优先级考虑在内:
if
如果您想在“其他”情况下取得成功而不做“其他”,请执行( <test>
-> <something 1>, % if test succeeds
...
<something N>
; <something else 1>,
...
<something else M>
)
:
true
生成结果
以上示例仍然使用您的( <test>
-> <something 1>, % if test succeeds
...
<something N>
; true
)
方法向用户显示结果。这不是在Prolog中实现它的规范方法。更好的是定义一个谓词,比如write
,它将连续提供num(X, Y, R)
的值,使其在回溯时成为现实。这是对上述案例的一个小修改:
R
或者
num(X, Y, R) :-
% `between` will first instantiate N with X.
% On backtracking, it will instantiate N with successive values
% and succeed until the value exceeds Y. Then it will fail.
%
between(X, Y, R),
<do some calls with R>. % Succeed if R passes criteria
然后每个回溯产生每个结果:
num(X, Y, X) :-
% NOTE: if X and Y are given, then their values CANNOT BE CHANGED
% in this predicate clause!
%
X =< Y, % num(X, Y) succeeds only if X =< Y
<do some calls with X and/or Y>. % Succeed if X passes criteria
num(X, Y, R) :-
X < Y,
X1 is X + 1,
num(X1, Y, R).
答案 1 :(得分:1)
没有什么可以添加到有价值的潜伏者的评论......
他建议的地方
您似乎试图将其用作赋值语句,但这不起作用。 Prolog不做任务。它确实存在。
你应该推断出对循环的一些含义。你的代码不能工作,因为它缺少'generate-and-test'的'generate'部分,你已经在故障驱动的循环中编码了。
所以,要么添加一个生成器,比如在/ 3之间,要么使用递归,而不是故障驱动的循环。
这是一个可能帮助您完成作业的1班轮。
?- [user].
|: num(X,Y) :- between(X,Y,N), number_codes(N,Cs), aggregate(sum(D),C^(member(C,Cs),D is C-0'0),6), writeln(N).
?- num(100,200).
105
true ;
114
true ;
123
true ;
132
true ;
141
true ;
150
true ;
false.