在Prolog中使用列表

Working with lists in Prolog

首先,我要说这是作为家庭作业进行的类练习的一部分。但是,整个任务比这个问题的主题要复杂得多。所以..

我正在搜索给定谓词的两个列表。我的目标是比较此列表中的相应元素,并确定第一个元素是否更大。如果是这样,那么我最终需要返回所有这些项的总和。这是我到目前为止的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.

我将尝试对您的代码进行尽可能小的更改。

绝对错误的一件事是您尝试计算差异。仅当使用is运算符时,Prolog才进行算术计算。您的代码:

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

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

如果您重写if的第一个子句,则如下所示(即使您在此也应该删除该is)将起作用:

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

这样,您的if谓词将从表达式中获得X和Y以便进行比较。

此外,您需要避免使用if谓词来产生两个可能的答案。即使在回溯过程中,当X> Y:时,也会调用第二个if子句。最简单的方法是将!放在第一个子句的末尾。它的意思是:"到目前为止,我接受了该程序中的第一个解决方案,并且我不想从这里返回以找到其他任何解决方案"。该子句将更改为:

1
2
3
4
if((X-Y), Iresult, Entry) :-
    X > Y,
    Iresult is Entry,
    !.

但是...这在小型程序中很好,如果您确实需要在程序的其他部分回溯,则可能会破坏它。较干净的方法是检查两个子句中的适当条件。将它们重写为:

1
2
3
4
5
6
7
if((X-Y), Iresult, Entry) :-
    X > Y,                                          
    Iresult is Entry.

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

然后,您确定如果X> Y,则第二个子句将失败。

进行这些修改后,您的代码应该可以正常工作……如果不能,请报告。
不过,它仍然不是很开篇。这有点太冗长。

编辑:

好吧,我会用一种简单的方式写它:

1
2
3
4
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).

...或以尾递归方式:

1
2
3
4
5
6
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).