Related
For my assignment I need to create a list of all the possible shifts (rotations) of another list in prolog. For example,
Prototype: all_shifts(+A,-R,+L,+S) *S will always start at 1*
?- length([1,2,3,4],L), all_shifts([1,2,3,4],R,L,1).
L = 4,
R = [[2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]].
Currently, I have a program that shifts it to the left once.
one_shift(A, R) :-
rotate(left, A, R).
rotate(left, [H|T], L) :- append(T, [H], L).
However, I need to create another program in which the final result (R) contains all of the possible shifts. Recursion in prolog is really beginning to confuse me, but I'm pretty sure that's whats required. Any help would be really appreciated.
Stay logically pure using same_length/2 and append/3!
list_rotations(Es, Xss) :-
same_length(Es, [_|Xss]),
rotations_of(Xss, Es).
rotations_of([], _Es).
rotations_of([Xs|Xss], Es) :-
same_length([_|Xss], Suffix),
same_length(Es, Xs),
append(Suffix, Prefix, Xs),
append(Prefix, Suffix, Es),
rotations_of(Xss, Es).
Sample query:
?- list_rotations([A,B,C,D], Xss).
Xss = [[B,C,D,A],
[C,D,A,B],
[D,A,B,C]]. % succeeds deterministically
A solution to your problem could be:
rotatelist([H|T], R) :- append(T, [H], R).
rotate(L,LO,LL):-
rotatelist(L,L1),
\+member(L1,LO),!,
append([L1],LO,L2),
rotate(L1,L2,LL).
rotate(_,L,L).
?- rotate([1,2,3,4],[],L).
L = [[1, 2, 3, 4], [4, 1, 2, 3], [3, 4, 1, 2], [2, 3, 4, 1]]
Simply rotates the list and checks if this list has already been inserted in the output list. If not the recursion continues, otherwise it returns the list in L. I've inserted the cut ! just to have only the list with all the possible rotations. If you want generate also the other lists just remove it...
If instead you want a solution with the prototype you provide, it could be:
rotatelist([H|T], R) :- append(T, [H], R).
all_shifts(_,[],I,I).
all_shifts(L,Result,Len,I):-
I < Len,
rotatelist(L,LO),
I1 is I+1,
all_shifts(LO,R1,Len,I1),
append([LO],R1,Result).
?- length([1,2,3,4],L), all_shifts([1,2,3,4],R,L,1).
L = 4,
R = [[2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]
The idea is basically the same as before... Note that this second solution is not tail recursive.
I want to create an intersection of lists of lists in prolog. (Matrix, with lists as cells)
I have to handle only the case, when number of rows and columns are the same (Rectangular). The lists are ordered, and does not contain any duplicate elements (they are ord_sets).
How could I do that?
Example: (3 rows, 3 columns)
A:
[[[1,2],[3,2,1],[3,4,5]],
[[1,2],[3,2,1],[3,4,5]],
[[1,2],[3,2,1],[3,4,5]]]
B:
[[[1],[3,2,1],[3,4,5]],
[[1,2],[2,1],[3,4]],
[[1,2],[3,2,1],[3,9,10,4,5]]]
C:
[[[1],[3,2,1],[3,4,5]],
[[1,2],[2,1],[3,4]],
[[1,2],[3,2,1],[3,4,5]]]
Thank you for the help!
Most Prolog interpreters already have a predicate to calculate the intersection between two lists: intersection/3. For example:
?- intersection([3,2,1], [3,9,10,4,5], R).
R = [3].
We can use maplist/3 to process an entire row of such lists:
?- maplist(intersection, [[1,2],[3,2,1],[3,4,5]], [[1],[3,2,1],[3,4,5]], C).
C = [[1], [3, 2, 1], [3, 4, 5]].
And by using another maplist/3 we process the matrices:
?- maplist(maplist(intersection),[[[1,2],[3,2,1],[3,4,5]], [[1,2],[3,2,1],[3,4,5]], [[1,2],[3,2,1],[3,4,5]]], [[[1],[3,2,1],[3,4,5]],[[1,2],[2,1],[3,4]],[[1,2],[3,2,1],[3,9,10,4,5]]], C).
C = [[[1], [3, 2, 1], [3, 4, 5]], [[1, 2], [2, 1], [3, 4]], [[1, 2], [3, 2, 1], [3, 4, 5]]].
So we can do the processing with:
intersect_matrix(A, B, C) :-
maplist(maplist(intersection), A, B, C).
I am trying to write a Prolog code, but I can't get this to return true. I am trying to find a list, which all elements are included in two other lists. For example all list A elements are found in B and C lists each, not together.
My Prolog code is :
member(X, [X|_]).
member(X, [_|T]) :-
member(X, T).
first([H0|T0], [H0|T1], A) :-
member(H0, A),
first(T0, [H0|T1], A).
first([H0|T0], [_|T1], A) :-
first([H0|T0], T1, A).
where member predicate returns true if an element is in a list. With predicate 'first' I am trying to use member predicate to find a matching element of A and B in C list. If I find, then go further in the first list and compare its first element to second lists elements and again, if I would matching, I check with if I can find it in third list. I hope it does this, but when I run
?- first([4, 6, 4], [4, 5, 6, 4], [1, 2, 4, 6]).
it gives false and I can't figure out why. This seems as a simple attention mistake somewhere, but I just can't get my head around it.
I don't know anything about prolog, but like everyone I've been bitten by logic errors before. (=
As I have commented, you seem to lack a base case for first([], _, _). An example:
first([4], [4], [4]) :-
member(4, [4]), // quite true
first([], [4], [4]). // No matching rule, as all those assume an existing head in the first argument
I am not sure I understood your question, but allow me to try to specify further your predicate first/3:
first(+L, +L1, +L2)
succeeds if every element of L is found either in L1 or in L2.
If this is what you're looking for, then:
first([], _, _).
first([E|L], L1, L2) :-
(member(E, L1); member(E, L2)),
first(L, L1, L2).
Examples of success:
first([1, 2, 3], [1, 2, 3], [1, 2]).
first([1], [1, 2, 3], [1, 2]).
first([1, 2, 3], [1, 2, 3], []).
Examples of faiure:
first([1, 2, 3, 5], [1, 2, 3], [1, 2]).
first([7], [1, 2, 3], [1, 2]).
first([1, 2, 3], [], []).
How can I reverse pairs of some list in Prolog?
For example:
?- reversePairs([1,2,3,4,5,6,7,9], R).
R = [2,1,4,3,6,5,9,7]. % expected answer
So far, I have written the following code:
reversePairs([X,Y|Xs], ReversedList) :-
reversePairs([X,Y|Xs], [], ReversedList).
reversePairs([], ReversedList, ReversedList).
reversePairs([X,Y|Xs], Accum, ReversedList) :-
reversePairs(Xs, [X,Y|Accum], ReversedList).
My code gives me the following answer:
?- reversePairs([1,2,3,4,5,6,7,9], R).
R = [7,9,5,6,3,4,1,2]. % observed answer
How can I correct my code to get the answer I want? Any suggestion?
Simply :
reversePairs([],[]).
reversePairs([X,Y|T], [Y,X|RT]) :-
reversePairs(T, RT).
This code fails if the number of elements is odd. What do you want to do for this case ?
Here's a funny possibility with DCGs:
reverp, [B,A] --> [A,B], !, reverp.
reverp --> [].
reversePairs(L1,L2) :- phrase(reverp,L1,L2).
It will also work on lists with odd number of elements.
Sample query:
?- reversePairs([1,2,3,4,5,6,7,9], R).
R = [2, 1, 4, 3, 6, 5, 9, 7].
?- reversePairs([1,2,3,4,5,6,7,8,9], R).
R = [2, 1, 4, 3, 6, 5, 8, 7, 9].
Can be easily generalized to N elements:
revern(N), Lr --> { length(L,N) }, L, !, { reverse(L,Lr) }, revern(N).
revern(_) --> [].
reverseNuples(N,L1,L2) :- phrase(revern(N),L1,L2).
Sample query:
?- reverseNuples(3,[1,2,3,4,5,6,7,9],R).
R = [3, 2, 1, 6, 5, 4, 7, 9].
As #repeat mentions in a comment below, reversePairs is not symmetric: the query
?- reversePairs(L,[2,1,4,3,6,5]).
will loop forever. To fix that, we can use same_length/2, to ensure that both terms are lists with same length:
reversePairs(L1,L2) :-
same_length(L1,L2),
phrase(reverp,L1,L2).
So I'm totally new to Prolog and need some help. I'm trying to take a list of lists like [[1,2,3],[4,5,6],[7,8]] and create a list like [2,3,5,6,8], so basically all the values into a new list besides the first of each list. I got this:
test5(X,[[_|X]|_]).
test5(X,[_|A]) :- test5(X,A).
which returns [2,3] and then [5,6] and then [8] each time I press enter. I'm not sure how to make them run all at once and make them into a list. I tried using append in different ways but I could not get this working. Any idea on how to implement this? Thanks!
You have the common predicate flatten/2, which almost does the job:
?- flatten([[1,2,3],[4,5,6],[7,8]], L).
L = [1, 2, 3, 4, 5, 6, 7, 8].
There are many implementations of flatten/2 available, just google it.
If you know that the list of lists is not nested, you should rather use append/2.
Then, you need to drop the first element of each list before appending:
list_tail([_|T], T).
Then:
?- maplist(list_tail, [[1,2,3],[4,5,6],[7,8]], T), append(T, L).
T = [[2, 3], [5, 6], [8]],
L = [2, 3, 5, 6, 8].
It might be a good exercise to take a more careful look at the implementation of append/2 linked above. With a small change in the definition (literally removing 1 character and adding 5) it will do the dropping and appending in the same step, without traversing the original list twice.
EDIT
So why is it that #repeat's initial solution does not terminate when the first argument is not a proper list, but the second is a proper list?
nt_tails_append([[_|T]|Ls], As) :-
append(T, Ws, As),
nt_tails_append(Ls, Ws).
It is because when the first argument to nt_tails_append/2 is a free variable, the first two arguments to append/3 above are variables, too. When we call append/3 in this mode, we get, by definition:
?- append(A, B, L).
A = [],
B = L .
In other words, the second and the third arguments are now unified. With the definition of nt_tail_append/2, this means that the recursive call gets the same second argument as the original call, and a new free variable as the first argument. This is an endless loop, of course.
(Tellingly, if you care to look at the definition of append/2 linked above, you will see that the first argument must_be a list.)
How does this help?
tails_append(Ls, As) :-
maplist(list_tail, Ls, T),
append(T, As).
list_tail([_|T], T).
The way that maplist is defined, all list arguments will be instantiated to proper lists. So you can safely use append/3 (here, used in the definition of append/2).
Here is how you could do it using append/3:
lists_concatenatedTails([],[]).
lists_concatenatedTails([[_|Xs0]|Xss],Ys) :-
append(Xs0,Ys0,Ys),
lists_concatenatedTails(Xss,Ys0).
Sample query:
?- lists_concatenatedTails([[1,2,3],[4,5,6],[7,8]], Xs).
Xs = [2, 3, 5, 6, 8].
Edit 2015-05-07
Note that the code that #Boris suggested (using list_tail/2,maplist/3,append/2) also gives answers for the following query:
?- maplist(list_tail,Xss,Yss), append(Yss,[1,2,3]).
Xss = [[_G97, 1, 2, 3]], Yss = [[1, 2, 3]] ;
Xss = [[_G97], [_G106, 1, 2, 3]], Yss = [[], [1, 2, 3]] ;
Xss = [[_G97, 1], [_G106, 2, 3]], Yss = [[1], [2, 3]] ;
Xss = [[_G97, 1, 2], [_G106, 3]], Yss = [[1, 2], [3]] ;
Xss = [[_G97, 1, 2, 3], [_G106]], Yss = [[1, 2, 3], []] ;
Xss = [[_G97], [_G106], [_G115, 1, 2, 3]], Yss = [[], [], [1, 2, 3]] ...
This doesn't terminate universally---nor do we expect it to: the set of solutions is infinite in size and it can, in this case, only be covered by an infinite sequence of answers.
In the following equivalent query lists_concatenatedTails/2 "loops" right away:
?- lists_concatenatedTails(Lss,[1,2,3]).
% not a single answer within finite time
Only when constraining the length of Lss right away, fair enumeration can be achieved:
?- length(Lss,_), lists_concatenatedTails(Lss,[1,2,3]).
Lss = [[_G23, 1, 2, 3]] ;
Lss = [[_G26], [_G29, 1, 2, 3]] ;
Lss = [[_G26, 1], [_G32, 2, 3]] ;
Lss = [[_G26, 1, 2], [_G35, 3]] ;
Lss = [[_G26, 1, 2, 3], [_G38]] ;
Lss = [[_G29], [_G32], [_G35, 1, 2, 3]] ...