Related
I am trying to check whether the interaction provided is the correct intersection of two lists. Example query list:
?- intersectionL([1,2,3,4],[1,3,5,6],[1,3]).
/* expected output: true. */
?- intersectionL([1,2,3,4],[1,3,5,6],X).
/* expected output: X = [1,3]. */
?- intersectionL([1,2,3],[4,3],[3]).
/* expected output: true. */
I have written a function to calculate the intersection of two lists (intersectionL). From there I want to verify whether the third argument given is the same as the intersection I found (intersectionHelper).
intersectHelper([], []).
intersectHelper([H1|T1], [H2|T2]):-
H1 = H2, intersectHelper(T1, T2).
intersectionL([], X, []).
intersectionL([H1|T1], L2, [H1|Res]):-
member(H1, L2), intersectionL(T1, L2, Res).
intersectionL([X|T1], L2, Res):-
intersectionL(T1, L2, Res).
I am having two problems: Firstly, how do I use intersectionHelper within intersectionL. Secondly, how do I output the list of intersections if no list is provided (like in query 2 above).
Edit: I was able to solve it for anyone else interested. I do not require intersectionHelper.
intersectionL([], X, []).
intersectionL([H1|T1], L2, [H1|Res]):-
member(H1, L2), intersectionL(T1, L2, Res).
intersectionL([X|T1], L2, Res):-
intersectionL(T1, L2, Res).
Not an answer but there I note that there is a RED CUT missing in intersectionL/3:
For example, computing the intersection of [1,2,3] and [1,4,5] gives two solutions, only one of which is desired:
?- intersectionL([1,2,3],[1,4,5],L).
L = [1] ; % desired
L = []. % not desired
We need to add a guard condition in the second clause:
intersectionL([], X, []).
intersectionL([H1|T1], L2, [H1|Res]):-
member(H1, L2), intersectionL(T1, L2, Res).
intersectionL([X|T1], L2, Res):-
\+member(H1, L2), intersectionL(T1, L2, Res).
or use a "red cut" to tell Prolog to not try the third clause if the second succeeded (this is ugly):
intersectionL([], X, []).
intersectionL([H1|T1], L2, [H1|Res]):-
member(H1, L2),!,intersectionL(T1, L2, Res).
intersectionL([X|T1], L2, Res):-
intersectionL(T1, L2, Res).
Best is to have an explicit guard with a green cut to shed any choicepoints that are of no use, while still staying declarative:
intersectionL([], _, []).
intersectionL([H1|T1], L2, [H1|Res]):-
member(H1, L2),!,intersectionL(T1, L2, Res).
intersectionL([H1|T1], L2, Res):-
\+member(H1, L2),!,intersectionL(T1, L2, Res).
Now it works, one solution only.
?- intersectionL([1,2,3],[1,4,5],L).
L = [1].
My problem is:
Write a Prolog program that, given two lists L1 and L2
, outputs
two new lists L3 and L4
such that L3 contains the elements of
L1 which also belong to L2
, while L4 contains the elements
of L1 which do not belong to L2
. You may use the built-in
predicate member.
As an example, the query listmem([a, r, t], [t, s, m, n, a], L3, L4)
produces L3 = [a, t] and L4 = [r].
And my solution is now:
memberOf([], [], _).
memberOf([H|T], L2, [X|Xs]) :-
X is H,
member(X, L2),
memberOf(T, L2, Xs).
But when I test on the following input, it returns no..
memberOf( [1,2,3], [2,3,4], L3 ).
What am I doing wrong?
listmem(L1,[],[],L1).
listmem([],_,[],[]).
listmem([H1|T1],L2,[H1|L3],L4):-
member(H1,L2), !,
listmem(T1,L2,L3,L4).
listmem([H1|T1],L2,L3,[H1|L4]):-
listmem(T1,L2,L3,L4).
I've added a cut to the third case instead of a \+ member(H1,L2) to the last one so you can use listmem the "other way around", e.g., instead of:
?- listmem([a, r, t], [t, s, m, n, a], L3, L4).
L3 = [a, t],
L4 = [r].
You can also:
?- listmem([a, r, t], L2, [a,t], L4).
L2 = [a, t|_G10554000],
L4 = [r].
Second day I am trying to make something like this work:
?- sm([1,2,3,4], [3,4,5,6], X).
X = [4,6,8,10].
I have something like this for now:
sm([], []).
sm([Head1|Rest1], [Head2|Rest2], R) :-
ResultElem is Head1 + Head2,
append([ResultElem], R, R1),
sm(Rest1, Rest2, R1).
I get only:
Singleton variables: [X]
false
Why does it not working and how this can finally be overcome?
The problem is that your recursive sm/3 does not have a matching base, because you wrote sm/2 by mistake:
sm([], [], []). /* You forgot the third pair of [] brackets */
As far as the recursive clause goes, it is easier to put the result in the header of the rule, and it lets you avoid using append:
sm([Head1|Rest1], [Head2|Rest2], [ResultElem|R]) :-
ResultElem is Head1 + Head2,
sm(Rest1, Rest2, R).
you can use maplist :
add(X,Y,Z) :-
Z is X+Y.
my_sum(L1, L2, L) :-
maplist(add, L1,L2,L).
With SWI-Prolog and module lambda, you can write
:- use_module(library(lambda)).
my_sum(L1,L2,L) :-
maplist(\X^Y^Z^(Z is X+Y), L1, L2, L).
Finally, with module clpfd, you can have:
:- use_module(library(lambda)).
:- use_module(library(clpfd)).
my_sum(L1,L2,L) :-
maplist(\X^Y^Z^(Z #= X+Y), L1, L2, L).
and we have :
?- my_sum([1,A, 9] ,[B,5,6], [5,7,C]).
A = 2,
B = 4,
C = 15.
I know if I do:
[H|T] = [a,b,c,d].
H = a,
T = [b,c,d].
What I'm trying to do is get the head and tail of a list inside a rule. Is this possible? I'm setting up base cases for a recursive call but for now I'd be satisfied if it just returned L3 as a append of the first list head and the second list head. I'm just not sure how I can get the head and list.
compose([], L1, L1).
compose(L2, [], L2).
compose([], [], []).
compose(L1, L2, L3) :-
[H1|T1] = L1,
[H2|T2] = L2,
append(H1, H2, L3).
I've also tried doing below based on what I've seen online:
compose([], L1, L1).
compose(L2, [], L2).
compose([], [], []).
compose([H1|T1], [H2|T2], L3) :-
append(H1, H2, L3).
but the trace fails on the Call to this predicate.In a successful case I would like it to do the following:
compose([a,b,c], [d,e,f], L).
L = [a, d].
at the very least for now.
compose([X|_],[Y|_], [X,Y]).
It is not more than that. Maybe you want to add cases for empty lists:
compose([], [], []).
compose([X|_], [], [X]).
compose([], [X|_], [X]).
I've written the following code in prolog:
contains(L1, []).
contains(L1, [X | T2]) :- member(X, L1), contains(L1, T2).
minus(L, [], L).
minus(L1, L2, L3) :- contains(L1, L3), nomembers(L3, L2).
nomembers(L1, []).
nomembers(L1, [X | T2]) :- not(member(X, L1)), nomembers(L1, T2).
contains(L1, L2) returns true if all of the members in L2 appear in L1. (contains([1,2],[1,1,1]) is true).
minus(L1, L2, L3) returns true if L3=L1\L2, meaning L3 consists of members of L1 but not of L2.
When I ask minus([1,2,3,4],[2,1],L), I get the answer that L=[], although logically it should be L=[3,4]. Does someone know why?
Above comment of mbratch is very helpful.
Notice, that your current minus(L1, L2, L3) definition is: All members of L3 are in L1 and no member from L3 is in L2.
Prolog is giving you good answer with L3 = [], it fits for definition I wrote above.
EDIT: Below code should do what you want, but currently I don't have prolog on my computer, so I can't test it.
remove(X, [X|T], T) :- !.
remove(X, [H|T], [H|T2]) :- remove(X, T, T2).
minus(L1,[],L1).
minus(L1,[H|T2],T3) :- member(H, L1), !, remove(H,L1,L4), minus(L4, T2, T3).
minus(L1,[H|T2],[H|T3]) :- minus(L1, T2, T3).
remove(X,LA,LB) which says: LB is LA without it first occurrence of X, so it's just removing element from the list.