I have an exam in Prolog today and am revising for it using old questions.
Would answer c be the incorrect answer? Can anyone please explain this to me? It would be very helpful. Thank you,
Consider the following predicate:
swap([], []).
swap([X1, X2 | L], [X2, X1 | S]) :- swap(L, S).
Which of the following query and answer pairs is incorrect:
(a) ?- swap([a,b,c,d], S).
S = [b, a, d, c].
(b) ?- swap([a,b,d], H).
false.
(c) ?- swap([a,a,b,b], S).
S = [b, b, a, a].
(d) ?- swap([], S).
S = [].
(c) is indeed the incorrect answer. Item (c) has the following query:
swap([a,a,b,b], S).
If you run this query manually, it clearly doesn't match the clause swap([], []). It then does match the second clause: swap([X1,X2|L], [X2,X1|S]) :-....
swap([a, a, b, b], S).
swap([X1, X2 | L], [X2, X1 | S]) :- swap(L, S).
==> X1 = a, X2 = a, L = [b, b]
==> swap([a, a| [b,b]], [a, a | S]) :- swap([b, b], S).
Prolog can instantiate the first argument [X1,X2|L] with the given list, [a,a,b,b]. That, then, means X1 = a, X2 = a, and the rest of the list, L = [b,b]. Already from this information, you know that the list [X2,X1|S] is [a,a|S] but the answer shown by (c) is [b,b,a,a]. You don't even need to find out what S because since you know alrady that [a,a|S] isn't going to match [b,b,a,a].
Related
I've written a tail-recursive predicate in Prolog which outputs the integers between A and B in a list K. I've used "reverse" to bring the numbers into the right order:
numbers(A,B,K) :- numbers(A,B,[],K).
numbers(Y,Y,X,K) :- !, reverse([Y|X],K).
numbers(A,B,X,K) :- A<B, C is A+1, numbers(C,B,[A|X],K).
Query:
?- numbers(3,6, K).
K=[3,4,5,6]
All works fine. What I now want to do is that I only want to have odd numbers of the range between A and B in the list K. How can I do that? Thanks in advance!
Firstly, I would try to avoid using reverse/2. If you have such a solution, it's often an indicator that there's a better way to get the answer forwards more directly. Not always, but most often. reverse/2 is probably the 2nd favorite band-aid in Prolog right behind use of the cut. :)
In many problems, an auxiliary accumulator is needed. In this particular case, it is not. Also, I would tend to use CLP(FD) operations when involving integers since it's the more relational approach to reasoning over integers. But you can use the solution below with is/2, etc, if you wish. It just won't be as general.
numbers(S, E, []) :- S #> E. % null case
numbers(X, X, [X]).
numbers(S, E, [S|T]) :-
S #< E,
S1 #= S + 1,
numbers(S1, E, T).
| ?- numbers(3, 8, L).
L = [3,4,5,6,7,8] ? ;
no
| ?- numbers(A, B, [2,3,4,5]).
A = 2
B = 5 ? ;
no
| ?-
This solution avoids reverse/2 and is tail recursive.
To update it for odd integers, the first thought is that we can easily modify the above to do every other number by just adding 2 instead of 1:
every_other_number(S, E, []) :- S #> E.
every_other_number(X, X, [X]).
every_other_number(S, E, [S|T]) :-
S #< E,
S1 #= S + 2,
every_other_number(S1, E, T).
| ?- every_other_number(3, 7, L).
L = [3,5,7] ? ;
no
| ?- every_other_number(3, 8, L).
L = [3,5,7] ? ;
no
| ?- every_other_number(4, 8, L).
L = [4,6,8] ? ;
no
| ?-
Then we can do odd numbers by creating an initial predicate to ensure the condition that the first value is odd and calling every_other_number/3:
odd_numbers(S, E, L) :-
S rem 2 #= 1,
every_other_number(S, E, L).
odd_numbers(S, E, L) :-
S rem 2 #= 0,
S1 #= S + 1,
every_other_number(S1, E, L).
| ?- odd_numbers(2, 8, L).
L = [3,5,7] ? ;
no
| ?- odd_numbers(2, 9, L).
L = [3,5,7,9] ? ;
no
| ?- odd_numbers(3, 8, L).
L = [3,5,7] ? ;
no
| ?-
This could be a solution, using mod/2 operator.
numbers(A,B,K) :-
B1 is B+1,
numbers(A,B1,[],K).
numbers(Y,Y1,X,K) :-
Y = Y1,
reverse(X,K).
numbers(A,B,X,K) :-
A<B,
C is A+1,
C1 is mod(C,2),
(C1 = 0 ->
numbers(C,B,[A|X],K)
; numbers(C,B,X,K)).
Another possibility is to use DCG :
numbers(A,B,K) :-
phrase(odd(A,B), K).
odd(A,B) --> {A > B, !}, [].
odd(A,B) --> {A mod2 =:= 0, !, C is A+1}, odd(C,B).
odd(A,B) --> {C is A+2}, [A], odd(C, B).
Very, VERY new to Prolog here. My function needs to compare two lists of equal length by taking the larger number into a new list (e.g. larger([3, 12, 5], [6, 3, 11], X) returns X = [6, 12, 11].) This is what I have, but it is not getting me what I need:
larger([],[],[]).
larger([H|T],[E|A],X):- H > E, larger([T],[A],[H|X]).
larger([H|T],[E|A],X):- H < E, larger([T],[A],[E|X]).
Any help is much appreciated.
The other answer is OK, this is a slightly different approach.
Two clauses should be enough:
larger([], [], []).
larger([X|Xs], [Y|Ys], [Z|Zs]) :-
/* Z is the larger number from (X, Y) */
larger(Xs, Ys, Zs).
How you do the part in the comments depends on your exact problem statement and maybe the implementation. At least SWI-Prolog and GNU-Prolog both have an arithmetic function max() that you can use like this in the above:
larger([], [], []).
larger([X|Xs], [Y|Ys], [Z|Zs]) :-
Z is max(X, Y),
larger(Xs, Ys, Zs).
This is arguably nicer than the solution with three clauses because it won't leave behind unnecessary choice points. Like the other solution, it will work fine as long as the two lists have numbers in them.
This would be identical to using a maplist, for example like this:
larger(Xs, Ys, Zs) :-
maplist(max_number, Xs, Ys, Zs).
max_number(X, Y, Z) :- Z is max(X, Y).
You're not far.
Try with
larger([], [], []).
larger([H | T], [E | A], [H | X]) :-
H > E,
larger(T, A, X).
larger([H | T], [E | A], [E | X]) :-
H =< E,
larger(T, A, X).
If I'm not wrong, there are three errors in your code.
(1) you have to translate the bigger head value (H or E) in the third argument of larger/3, not in the recursive call
% ------- H added here ---v
larger([H | T], [E | A], [H | X]) :-
H > E,
larger(T, A, X).
% not here ----^
(2) T and A, the tails in [H|T] and [E|A], are lists, so you have to pass they recursively as T and A, not as [T] and [A]
larger([H | T], [E | A], [H | X]) :-
H > E,
larger(T, A, X).
% not larger([T], [A], X)
(3) if you have the cases H > E and H < E, your code fail when H is equal to E; one solution is H > E and H =< E; the secon case cover H equal to E.
I am new to Prolog and I am having a little bit of trouble understanding recursion. I am trying to write a relation that finds the intersection of two sorted lists without using SWI's built-in intersect. I've used trace to see what's happening, and it's behaving as I expect up until the point where I want it to terminate and return the new list that contains the intersection. This makes me think that my base case is wrong. I've played around with several different ways of forming the base case, but it hasn't been fruitful. I've been using the lists [1, 2, 3, 4] and [2, 4, 6] as test cases with the following relations (the base case on top is just one I threw in as a placeholder... it doesn't work at all):
intersectS([], [], []).
intersectS([A | B], [C | D], Z) :- A < C, intersectS(B, [C | D], Z).
intersectS([A | B], [C | D], Z) :- A > C, intersectS([A | B], D, Z).
intersectS([A | B], [C | D], Z) :- A = C, append(Z, [A], Y), intersectS(B, D, Y).
Any help is appreciated. I've seen examples where the cut (!) operator is used alongside the member/non-member, but I'm supposed to take advantage of the fact that the lists are sorted so I thought I would try this approach. Thanks in advance.
Overall, the solution you have is partway there (as you observed). There are two areas that need fixing I think. One is, as you pointed out, the "base case". I would do it as follows:
intersectS([], _, []).
intersectS(_, [], []).
In other words, anything intersected with an empty list is empty.
The second trouble spot is the clause for A = C. You have:
intersectS([A | B], [C | D], Z) :- A = C, append(Z, [A], Y), intersectS(B, D, Y).
Which says that if the heads of the two lists match, then the intersection (Z) appended with [A] (the matching head) is the intersection of the tails of the two lists. This doesn't seem correct. I think you want to say that the intersection (Z) is the intersection of the tails B and D appended to [A], which looks like this:
intersectS([A | B], [C | D], Z) :- A = C, append([A], Y, Z), intersectS(B, D, Y).
So the whole thing looks like:
intersectS([], _, []).
intersectS(_, [], []).
intersectS([A | B], [C | D], Z) :- A < C, intersectS(B, [C | D], Z).
intersectS([A | B], [C | D], Z) :- A > C, intersectS([A | B], D, Z).
intersectS([A | B], [C | D], Z) :- A = C, append([A], Y, Z), intersectS(B, D, Y).
You can take it a step further and get rid of the append since you're just dealing with one element. append([A], Y, Z) is the same as saying Z = [A|Y]. So you can replace the last clause with simply:
intersectS([A | B], [C | D], [A | Y]) :- A = C, intersectS(B, D, Y).
Running your test case:
?- intersectS([1, 2, 3, 4], [2,4,6], L).
L = [2, 4] ;
false.
?-
Hey I'm trying to append two list with no "double" members
for example
A = [a, b, c]
B = [x, c, q]
then ->
append2(A,B,P)
P= [a,b,c,x,q]
I write this code, but it doesn't work...
not_member(_, []).
not_member(X, [Y|Ys]) :- X \= Y, not_member(X, Ys).
append2(A, [], A).
append2([], A, A).
append2([h1|ls], B, [h1|P]) :- not_member(h1, B), !, append2(ls, B, P).
append2([h1|ls], B, P) :- member(h1, P), append2(ls, B, P).
Thanks for helping :)
Assuming there are no variables in your input lists, but allowing duplicates in each list you may write:
append2(A,B,C):-
findall(Item, append2_item(A,B,Item), C).
append2_item(A,_,ItemA):-
append(HeadA, [ItemA|_], A),
\+ member(ItemA, HeadA).
append2_item(A,B,ItemB):-
append(HeadB, [ItemB|_], B),
\+ member(ItemB, HeadB),
\+ member(ItemB, A).
First clause of append2_item/3 selects (ordered) distinct items from the first list. Second clause of append2_item/3 selects (ordered) distinct items from the second list which are not present in the first list.
append2/3 just collects those elements.
Test case:
?- append2([a,b,c,a],[x,c,q,x],C).
C = [a, b, c, x, q].
Check out the pure code in my answer
to the related question "intersection and union of 2 lists"!
Telling from your requirements, predicate list_list_union/3 is just what you are looking for:
?- list_list_union([a,b,c],[x,c,q],Ls).
Ls = [a,b,c,x,q]. % succeeds deterministically
list_list_union/3 is monotone, so we get sound answers
even when using non-ground terms:
?- As = [_,_,_], Bs = [_,_,_], list_list_union(As,Bs,Ls), As = [a,b,c], Bs = [x,c,q].
As = [a,b,c], Bs = [x,c,q], Ls = [a,b,c,x,q] ; % logically sound result
false.
I'm writing a permutation function [a,b]-->[[[a], [b]], [[a, b]]
I have this so far, but it doesn't work.
perm([],[]).
perm(L,[H|T]) :- append(V,[H|U],L), append(V,U,W), perm(W,T).
Given your example, it looks like you might actually be wanting the powerset, not the permutation, of the given list.
For instance, the powerset of [a,b] is the set {[a,b], [a], [b], []}.
To compute the powerset of a list of items in Prolog, look at this answer by #gusbro. If this helps you, also please upvote that answer.
If you want all solutions of the powerset of a list L at once, you can wrap the call to powerset/2 in a findall/3 call like this:
?- findall(S, powerset(L, S), Ss).
If, on the other hand, you're after the partitions (as you've mentioned in one of your earlier edits), consider the following:
partition(L, PL) :-
partition(L, [], PL).
partition([], [], []).
partition([X|Xs], As, R) :-
% add X into the new partition...
append(As, [X], NewAs),
partition(Xs, NewAs, R).
partition(L, [A|As], [[A|As]|R]) :-
% ...or, collect the current non-empty partition
partition(L, [], R).
The predicate partition/2 takes a list and returns all partitions, as you've described. For example:
?- partition([a,b,c],L).
L = [[a, b, c]] ;
L = [[a, b], [c]] ;
L = [[a], [b, c]] ;
L = [[a], [b], [c]] ;
false.
Really? It seems to work in SWI-Prolog:
?- [user].
|: perm([],[]).
|: perm(L,[H|T]) :- append(V,[H|U],L), append(V,U,W), perm(W,T).
|: % user://1 compiled 0.00 sec, 3 clauses
true.
?- perm([a,b,c], X).
X = [a, b, c] ;
X = [a, c, b] ;
X = [b, a, c] ;
X = [b, c, a] ;
X = [c, a, b] ;
X = [c, b, a] ;
false.
?- perm([a,b,c,d], X).
X = [a, b, c, d] ;
/* trimming 22 solutions */
X = [d, c, b, a] ;
false.
This also yields the number of answers you'd expect: 3! = 6, 4! = 24. What's not working for you?
Quick note: Prolog doesn't offer functions, but relations.
In this case, perm/2 will hold true when the arguments are one the permutation of the other.
I find this definition more readable than your.
perm([], []).
perm([E|Es], P) :-
perm(Es, Q),
select(E, P, Q).
It's almost the same as that of permutation/2 SWI-Prolog, but hides a bug...