Prolog: comparing the respective elements in 2 lists

211 Views Asked by At

I have 2 lists [x1, x2, ...xn] and [y1, y2, ...yn] of the form {0, 1}^n.

I want to generate a new list [a1, a2 ... an] such that ai = xi AND yi for every i from 1 to n (i.e., if x1 = y1 = 1 then a1 = 1 or if x1 = 1, y1 = 0, then a1 = 0)

How can I implement a predicate using recursion?

2

There are 2 best solutions below

2
repeat On

Use and maplist/4 together with Prolog lambdas like this:

?- use_module([library(clpb),library(lambda)]).
true.

?- maplist(\A^B^AB^sat(A*B =:= AB),
           [1,1,0,0],
           [1,0,0,1],
           Products).
Products = [1,0,0,0].
4
AudioBubble On

Disclaimer: This answer is just a more explicit version of the comment by @lurker for posterity.

First, how do you do the AND? One simple option is to use a bitwise AND:

and(A, B, R) :- R is A /\ B.

Now, what you want is as simple as:

?- maplist(and, [1, 0, 0, 1], [0, 1, 0, 1], L).
L = [0, 0, 0, 1].

What is this maplist? Since SWI-Prolog's code is both available and easy to browse, you can look at the standard library definition:

maplist(Goal, List1, List2, List3) :-
    maplist_(List1, List2, List3, Goal).

maplist_([], [], [], _).
maplist_([Elem1|Tail1], [Elem2|Tail2], [Elem3|Tail3], Goal) :-
    call(Goal, Elem1, Elem2, Elem3),
    maplist_(Tail1, Tail2, Tail3, Goal).

This is more general than you probably need. First, you don't need to pass and/3 to the predicate that you want to write, you can simply inline it. So, you will replace the call with and or just with the is. Now you also won't need to reorder the arguments, so you don't need to have a predicate and a helper predicate.

There is so much code out there, it is a shame not to look at it and try to learn.