使用Prolog中的列表

时间:2009-11-20 00:55:52

标签: prolog

首先请允许我声明这是作为家庭作业的课堂练习的一部分。但是,整个任务比这个问题的主题更复杂。所以..

我正在搜索给出预测的两个列表。我的目标是比较此列表中的相应元素,并确定第一个元素是否更大。如果是,那么我需要最终返回所有这些术语的总和。以下是我到目前为止的情况:

isumrow([], [], Iresult) :- 
    Iresult is 0.
isumrow([Hi1row | Ti1row], [Hi2row | Ti2row], Iresult) :-   
    if((Hi1row - Hi2row), IsumDiff, Hi1row),
    NewIresult is IsumDiff + Iresult,
    isumrow(Ti1row, Ti2row, NewIresult),
    Iresult is NewIresult.

if(Diff, Iresult, Entry) :-
    Diff > 0,                       

    Iresult is Entry.

if(_, Iresult, _) :-
    Iresult is 0.

出于某种原因,我在我的任务中某处乱搞,我不确定在哪里。任何提示将不胜感激。同样,这是我工作的更大任务的一部分,但我无法得到它。感谢

2 个答案:

答案 0 :(得分:1)

isumrow([], [], Iresult) :-
    Iresult is 0.

isumrow([Hi1row | Ti1row], [Hi2row | Ti2row], Iresult) :-
    if((Hi1row - Hi2row), IsumDiff, Hi1row),              
    NewIresult is IsumDiff + Iresult, 
    isumrow(Ti1row, Ti2row, NewIresult), 
    Iresult is NewIresult. 

if(Diff, Iresult, Entry) :- 
    Diff > 0,                                            
    Iresult is Entry. 

if(_, Iresult, _) :- 
    Iresult is 0. 

答案 1 :(得分:0)

我会尝试尽可能少地为您的代码引入更改。

绝对错误的一件事是你试图计算差异的地方。 Prolog仅在使用is运算符时才进行算术运算。你的代码:

if((Hi1row - Hi2row), IsumDiff, Hi1row),

只是将表单(X-Y)的表达式传递给if谓词,而不是计算它。稍后在if内部,您不计算差异,但尝试将表达式与零进行比较...失败,因为您只能将数字与数字进行比较,而不是与表达式进行比较 - 并且Diff得到分配给表达式。

如果你重写if的第一个子句如下(即使你也应该在这里删除is),它会起作用:

if((X-Y), Iresult, Entry) :-
    X > Y,
    Iresult is Entry.

这样,您的if谓词将从表达式中获取X和Y,以便能够比较它们。

此外,您需要避免使用if谓词来产生两个可能的答案。即使X> Y:在回溯过程中,也会调用第二个if子句。最简单的方法是将!放在第一个子句的末尾。这意味着:“到目前为止,我接受了该计划中的第一个解决方案,我不想再从这里找回任何其他解决方案”。该条款将改为:

if((X-Y), Iresult, Entry) :-
    X > Y,
    Iresult is Entry,
    !.

但是......这在小程序中很好,如果你真的需要在程序的其他部分进行回溯,这可能会破坏它。更清洁的方法是检查两个条款中的正确条件。将它们改写为:

if((X-Y), Iresult, Entry) :-
    X > Y,                                           
    Iresult is Entry.

if((X-Y), Iresult, _) :-
    X =< Y,
    Iresult is 0.

然后你确定如果X&gt; Y,第二个子句将失败。

经过这些修改后,您的代码应该正常工作......如果没有,请报告。 尽管如此,它仍然不会很顺利;它有点过于冗长。


编辑:

好的,我会以一种简单的方式写出来:

sum_if_bigger([], [], 0).
sum_if_bigger([A|L1], [B|L2], Result) :-
        sum_if_bigger(L1, L2, Partial),
        Result is Partial + max(0, A-B).

...或以尾递归的方式:

sum_if_bigger_tr(L1, L2, R) :-
        sum_if_bigger_tr(L1, L2, 0, R).
sum_if_bigger_tr([], [], R, R).
sum_if_bigger_tr([A|L1], [B|L2], Partial, Result) :-
        NewPartial is Partial + max(0, A-B),
        sum_if_bigger_tr(L1, L2, NewPartial, Result).