坚持prolog程序

时间:2015-02-11 01:43:06

标签: prolog

所以我遇到了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),!.

2 个答案:

答案 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进行实例化。此时,YX的值现在从不在谓词子句执行过程中发生变化。表达式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)查询中从一个整数迭代到另一个整数(从XY。如何在没有回溯的情况下使用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.