English 中文(简体)
Working with lists in Prolog
原标题:
  • 时间:2009-11-20 00:55:52
  •  标签:
  • prolog

First off let me state that this is part of a class exercise given as homework. But, the entire assignment is much more involved than the subject of this question. So..

I am searching through two lists given to a predication. My goal is to compare the corresponding elements in this list and determine if the first one is larger. If it is then I need to eventually return a sum of all of those terms. Here is what I have so far:

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.

For some reason I am messing up somewhere in my assignments and im not sure where. Any hints would be appreciated. Again, this is part of a much larger assignment that I have working but I cannot get this. Thanks

问题回答
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. 

I ll try to introduce as little changes as possible to your code.

One thing that is definitely wrong is where you try to calculate the difference. Prolog does arithmetic computations only when using is operator. Your code:

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

is merely passing the expression of the form (X-Y) to the if predicate, and not calculating it. Later inside if, you do not compute the difference but try to compare the expression to zero... which fails, because you can only compare numbers to numbers, and not to expressions -- and Diff gets assigned to an expression.

It would work if you rewrite the first clause of if as follows (even though you should also get rid of that is here):

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

This way your if predicate will get X and Y from the expression to be able to compare them.

Also, you need to avoid your if predicate to yield two possible answers. Your second if clause will be invoked even when X>Y: in the process of backtracking. The easiest way is to put ! at the end of first clause. It means: "Up to this point, I accept the first solution in this program and I don t want to go back from here to find any other solutions". The clause will be changed to:

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

But... this is good in small programs, and if you actually need backtracking in other parts of your program, this can break it. The cleaner way would be to check proper condition in both clauses. Rewrite them to:

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

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

Then you re sure that if X>Y, the second clause will fail.

After these modifications your code should work... Please report if it doesn t. It still won t be very prolog-ish though; it is a little bit too verbose.


Edit:

Ok, I d write it in a simple way:

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).

...or in a tail-recursive way:

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).




相关问题
Prolog : Learning by example

I am trying to learn a little bit about swi-prolog (beyond the basic, useless programs). Can anyone explain (perhaps in pseudocode) what this sudoku solver and the related functions are doing? If ...

Working with lists in Prolog

First off let me state that this is part of a class exercise given as homework. But, the entire assignment is much more involved than the subject of this question. So.. I am searching through two ...

SWI-Prolog conditional statements

I m trying to write a function that will test to see if the word hello is contained in a list. If it is contained, i don t want it to say "true", i want it to say : "yes, the word hello is contained ...

prolog cut off in method

I have a question I would like to ask you something about a code snippet: insert_pq(State, [], [State]) :- !. insert_pq(State, [H|Tail], [State, H|Tail]) :- precedes(State, H). insert_pq(State, [...

Max out of values defined by prolog clauses

I know how to iterate over lists in Prolog to find the maximum, but what if each thing is a separate clause? For example if I had a bunch of felines and their ages, how would I find the oldest kitty? ...

热门标签