Search code examples
prologlist-manipulation

Prolog - intern variables sum


I'm having some trouble trying to sum up some lists I have.

I'm currently having:

[[[_G8511,0,1,_G8520],[_G8526,1,0,0],[_G8541,_G8544,0,1]],
 [[1,1,1,_G8568],[0,1,0,1],[0,_G8592,0,1]],
 [[1,0,_G8613,_G8616],[0,1,_G8628,0],[0,_G8640,_G8643,1]]]

My problem is that I try to sum up the elements inside the list. I know how to iterate through it, but I need to either ignore the intern variables, or make them into 0.

I tried using sum_list(List, Sum), but as I figured it can not handle intern variables. So my question is how can I either ignore the elements not having the value of 0 or 1, or how can I make the internal variables into 0?


Solution

  • You could use nonvar/1 predicate which succeeds when the argument is not a variable.

    You could write the sum_list predicate:

    sum_list(List,Sum):-flatten(List,List2),sum_list2(List2,Sum).
    
    sum_list2([],0).
    sum_list2([H|T],Sum):- var(H),sum_list2(T,Sum).
    sum_list2([H|T],Sum):- nonvar(H), sum_list2(T,Sum1),Sum is Sum1+H.  
    

    Note that in the above solution since you need the sum and lists are nested I used flatten/2 predicate which flatten a nested list into a flat list.

    ?- sum_list([[[_G8511,0,1,_G8520],[_G8526,1,0,0],[_G8541,_G8544,0,1]],[[1,1,1,_G8568],[0,1,0,1],[0,_G8592,0,1]],[[1,0,_G8613,_G8616],[0,1,_G8628,0],[0,_G8640,_G8643,1]]],Sum).
    Sum = 12 ;
    false.
    

    Another solution (deterministic) using foldl/4 could be:

    add(X,Y,Sum):- (nonvar(X)-> Sum is X+Y;Sum is Y).
    
    sum(List,Sum):- flatten(List,L2),foldl(add,L2,0,Sum).