if I have two lists in Prolog like
people([a, b, c]).
cols([green, red, yellow]).
I want to all permutations of theses list like this.
?- all triplets(X)
X = [ ((a,green),(b,red),(c,yellow)), ((a,green),(b,yellow),(c,red)), ((a,green),(c,red),(b,yellow)), ((a,green),(c,yellow),(b,red)), ((a,red),(b,green),(c,yellow)), ((a,red),(b,yellow),(c,green)), ((a,red),(c,green),(b,yellow)), ((a,red),(c,yellow),(b,green)), ((a,yellow),(b,green),(c,red)), ((a,yellow),(b,red),(c,green)), ((a,yellow),(c,green),(b,red)), ((a,yellow),(c,red),(b,green)), ((b,green),(a,red),(c,yellow)), ((b,green),(a,yellow),(c,red)), ((b,green),(c,red),(a,yellow)), ((b,green),(c,yellow),(a,red)), ((b,red),(a,green),(c,yellow)), ((b,red),(a,yellow),(c,green)), ((b,red),(c,green),(a,yellow)), ((b,red),(c,yellow),(a,green)), ((b,yellow),(a,green),(c,red)), ((b,yellow),(a,red),(c,green)),((b,yellow),(c,green),(a,red)), ((b,yellow),(c,red),(a,green)), ((c,green),(a,red),(b,yellow)), ((c,green),(a,yellow),(b,red)), ((c,green),(b,red),(a,yellow)), ((c,green),(b,yellow),(a,red)), ((c,red),(a,green),(b,yellow)), ((c,red),(a,yellow),(b,green)), ((c,red),(b,green),(a,yellow)), (p(c,red),(b,yellow),(a,green)), ((c,yellow),(a,green),(b,red)), ((c,yellow),(a,red),(b,green)), ((c,yellow),(b,green),(a,red)), ((c,yellow),(b,red),(a,green))],
what i have tried till now is this
list_pairs(Pairs) :-setof(p(X,Y),((people(Q),member(X,Q)),(cols(F),member(Y,F))),Pairs).
it gives me a list of pairs these two lists like this.
?- list_pairs(M),length2(M,L).
M = [p(a, green), p(a, red), p(a, yellow), p(b, green), p(b, red), p(b, yellow), p(c, green), p(c, red), p(..., ...)],
L = 9
Without just giving away a whole answer, if you really are looking for a matching, element-to-element of permutations of each list, then you'd want something like:
match_perm(List1, List2, MatchUp) :-
permutation(List1, PList1),
permutation(List2, PList2),
zip(Plist1, PList2, MatchUp).
permutation is a predicate already in the Prolog library. You'd need to write a predicate zip that takes two lists and just pairs up the corresponding elements. zip([a,b,c], [1,2,3], MatchUp) would yield MatchUp = [(a,1),(b,2),(c,3)]. If you really want ((a,1),(b,2),(c,3)) instead, that's a bit more work since (...) isn't a list form in Prolog.
Once you have match_perm, then you'd use findall on that.
Related
Problem: I need to transform this list: [[1,2],[3,4],[5,6]] to [1,3,5], by taking only first items from each sub-list in first list and creating new list with all of them. Language is SWI-Prolog.
My solution: To do this, I wrote this code:
getFirstItems([], Result).
getFirstItems([H|T], Result) :-
[H2|T2] = H,
append(Result,H2,Result2),
getFirstItems(T, Result2).
Issue: But this fails to infinite recursion when tail always equals to [[5,6]]
Question: how to solve this issue and solve this problem correctly?
You are complicating things too much. You need to reason with a declarative mindset, and thus implement what the relationships between the list of lists and the list of first elements are.
Here is a solution:
first_items([], []).
first_items([[H|_]|T], [H|T2]) :-
first_items(T, T2).
Indeed, the only two things we need to state to describe that relationship are:
If the list of lists is empty, then so is the list of first elements.
a first element H is in the list of first elements, followed by the first elements (T2) of the rest of the list of lists (T).
Example queries:
?- first_items([[1,2],[3,4],[5,6]], Z).
Z = [1, 3, 5].
?- first_items(L, [1,3,4]).
L = [[1|_22058], [3|_22070], [4|_22082]].
?- first_items(L, Z).
L = Z, Z = [] ;
L = [[_22048|_22050]],
Z = [_22048] ;
L = [[_22048|_22050], [_22066|_22068]],
Z = [_22048, _22066]
…
I am trying to get my head wrap around lists in Prolog. To do this I am trying to create a sort of game. You pass in a list of numbers 1-9 that can be repeated, the list can be any length. The rules are that starting from the first element(e) you can only move to e+2 or e+3 until you get to the end. The goal is to "land" on the highest numbers. In essence it is kind of like hopscotch. The problem I am running into is determining all the possible permutation for paths. So far I have the following.
paths([], []). %empty list returns empty list
paths([X], [X]). %list with one element returns that one element
paths([X1, X2], [X1]). %list with 2 elements returns the first element
paths([X1, X2, X3], [X1,X3]). %list with three elements returns the first and third element
paths() :- % the recursive case for a list with 4+ elements
An list to use would be: [1,2,3,4,5,6,8,7,9,3,6,5,7,8,9]
I need to determine all possible paths using the rule mentioned about. I wish lists could be indexed in Prolog :(
Any logic guidance would be appreciated.
The requirements aren't completely clear, but it seems that:
The second argument is required to have the same first element as the
first argument (you "hop" on the first "square" first always, using
your hopscotch metaphore)
You aren't requiring that the last element of the first list be the
last element of the second list (you aren't requiring that you "land
on" the last "square").
An empty list succeeds with an empty list result (rather than just failing on an empty list - which is another valid approach).
Then this could be implemented as follows. You do not need many explicit 2- and 3-element list cases since they are handled by the recursive clause and simpler base cases.
path([], []).
path([X], [X]).
path([X,_|T], [X|R]) :- % hop over 1 element
path(T, R).
path([X,_,_|T], [X|R]) :- % hop over 2 elements
path(T, R).
For a simple example:
| ?- path([1,2,3,4,5,6], R).
R = [1,3,5] ? ;
R = [1,3,6] ? ;
R = [1,4,6] ? ;
R = [1,4]
yes
If I don't have your requirements exactly right, you should be able to adjust this to suit your needs as it shows how to handle a recursive case. It also sounds like you are headed in the direction of trying to optimize the values in your hops, which I shall also leave as an exercise.
This can also be done with a DCG (definite clause grammar)
path([]) --> [].
path([X]) --> [X].
path([X|T]) --> ([X,_] | [X,_,_]), path(T).
Which would be exercised:
| ?- phrase(path(R), [1,2,3,4,5,6]).
R = [1,3,5] ? ;
R = [1,3,6] ? ;
R = [1,4,6] ? ;
R = [1,4] ? ;
(1 ms) no
| ?-
In light of the extra requirement that the last step taken must be one that falls within the list, here is an updated version of the path/2 predicate:
path([], []).
path([X], [X]).
path([X,_], [X]).
path([X,_,Y|T], [X|R]) :- % hop over 1 element
path([Y|T], R).
path([X,_,_,Y|T], [X|R]) :- % hop over 2 elements
path([Y|T], R).
I think that there is a reason to avoid indexing: simplicity. If you decompose your problem, maybe you could start writing a step/3 predicate like
step([_,X|T],X,T).
step([_,_,X|T],X,T).
and then
paths([],[]).
paths(L,[X|Xs]) :- step(L,X,T), paths(T,Xs).
note: I don't understand very well your game, some example of playground and solution would be welcome.
%passing in a list and return all possible paths using K+2 or K+3 with K being the first element of the list.
%empty list returns empty list
%list with one element returns that one element
%list with 2 elements returns the first element
%list with three elements returns the first and third element
%list with four/four+ elements needs to be called recursively, prefix them with the first element and append them together
%RL means ReturnList
%FL means FinalList
%List is the appended list containing all the paths
paths([], []).
paths([X], [[X]]).
paths([X1, X2], [[X1]]).
paths([X1, X2, X3], [[X1,X3]]).
paths([X1, X2, X3, X4 | T], List) :-
paths([X3,X4|T], RL), paths([X4|T], RL2),
prefix_all(X1, RL, FL1), prefix_all(X1, RL2, FL2),
append(FL1, FL2, List).
So if run with the list [1,2,3,4,5] is would produce the following:
| ?- paths([1,2,3,4,5],X).
X = [[1,3,5],[1,4]] ? ;
no
I'm not really good with lists in Prolog. What I'm trying to do is to split one list [1,2,3,4] into two lists. The catch is that the elements of those two lists can be in any order.
This is what I have right now:
divideList([],[],[]).
divideList(L1,L2,[H|T]) :-
select(H,L1,L1C),
length(L1,Length1),
length([H|T],LengthHT),
Length1 =< LengthHT,
divideList(L1C,L2,T).
divideList(L1,L2,[H|T]) :-
select(H,L2,L2C),
length(L2,Length2),
length([H|T],LengthHT),
Length2 =< LengthHT,
divideList(L1,L2C,T).
It works when I put in all the lists and it just has to check if it's true or false.
?- divideList([1,2],[4,3],[1,2,3,4]).
true .
?- divideList([2,1],[4,3],[1,2,3,4]).
true .
?- divideList([2,1],[3,4],[1,2,3,4]).
true .
However if I try to do this: ?- divideList(A,[3,4],[1,2,3,4]).
It shows me this ERROR: Out of global stack .
When I want it to show me this:
?- divideList(A,[3,4],[1,2,3,4]).
A = [1,2] ;
A = [2,1].
Any ideas on how to fix this?
You could simplify it a bit using permutation/2:
divideList([A|As], [B|Bs], L) :-
permutation(L, P),
append([A|As], [B|Bs], P).
The [A|As] and [B|Bs] prevent [] from being a solution for the first or second argument.
I need some help with three prolog predicates for checking and manipulating lists. I'm new to prolog and any help would be much appreciated.
The three predicates are:
double_up(+List1, -List2) is true when List2 has each element of List1 twice. The query double_up([a,b,c],X) should give X=[a,a,b,b,c,c]. The order of the elements in the output list does not matter.
pivot(+List1, +Pivot, -Smaller, -GreaterEq) is true when Smaller is the list of numbers in List1 smaller than Pivot, and GreaterEq is the list of numbers in List1 bigger than or equal to Pivot.
fancy_replace(+List, +Takeout,+Putin, -NewList, -Count) is true when NewList is the same list as the input List, but where each Takeout element in the list is replaced with the Putin element. Count should be the number of Takeouts that got replaced. For example, the query fancy_replace([9,10,1,9,2],9,0, X, C) should give X = [0,10,1,0,2] and C = 2. The order of the elements in the output list does not matter.
The simpler pattern to process lists in Prolog imposes a recursive predicate with 2 arguments, matching - conventionally - input and output data, and a base case, stopping the recursion, matching the empty list. Then
double_up([X|Xs], [X,X|Ys]) :- double_up(Xs, Ys).
double_up([], []).
This predicate it's a bit more general than what's required, because it works also in mode double_up(-List1, +List2). For instance
?- double_up(L,[1,1,2,2]).
L = [1, 2].
To restrict its mode as required, I think it's necessary to uselessly complicate the code, moving that clean loop in a service predicate, and leaving double_up just to test the arguments:
double_up(I, O) :- is_list(I), var(O), double_up_(I, O).
double_up_([X|Xs], [X,X|Ys]) :- double_up_(Xs, Ys).
double_up_([], []).
pivot/4 could be 'one-liner' in SWI-Prolog:
pivot(List1, Pivot, Smaller, GreaterEq) :-
partition(>(Pivot), List1, Smaller, GreaterEq).
like partition, foldl from library(apply) it's an easy inplementation of the last required predicate:
fancy_replace(List, Takeout, Putin, NewList, Count) :-
foldl(swap_n_count(Takeout, Putin), List, NewList, 0, Count).
swap_n_count(Takeout, Putin, L, N, C0, C) :-
( L == Takeout
-> N = Putin, C is C0 + 1
; N = L, C = C0
).
to be honest, i hate prolog... even though it is fun and easy after you learn it
i think this is a good reference as I was having trouble understanding how prolog works couple weeks ago.
what does the follow prolog codes do?
anyway.. this is the answer for your first problem; Hopefully you could solve the rest yourself :D
double([]).
double([H|[]], [H,H|[]]).
double([H|T],[H,H|T1]):- double(T, T1).
btw, this might not the only solution...but it works
The built-in predicate member(x, List) checks if a member exists in a list, but when there are lists within lists it only checks the first depth. I'm trying to find out exactly what depth a member is in. For example:
?- memberDepth(a, [b, c, [d], [[e, f, [], [g], a], j], [k]], Depth).
Depth = 3 .
So basically, it finds the depth of the first instance of 'a' in the list. If the member doesn't exist, it'll return Depth = 0. It would also be useful if I could find the depth of all instances of the member in order, for example:
?- memberDepthAll(a, [b, c, [a], [[e], a], [[a]]], Depth).
Depth = 2 ;
Depth = 2 ;
Depth = 3 ;
Depth = 0 ;
false.
I'm very new to prolog so any help would be appreciated.
Note that, if at any point the second argument isn't a list, none of the rules will match. Also, you could use member to check at the top level, but since we have to break down the list to go deeper, I check each element individually, which avoids duplicating work or needed an auxiliary predicate.
% First, check the first element of the list
memberDepth(X,[X|_],0).
% Next search inside the first element of the list (hence the +1)
memberDepth(X,[H|_],D1) :- memberDepth(X,H,D), D1 is D+1.
% FInally, search the rest of the list
memberDepth(X,[_|T],D) :- memberDepth(X,T,D).
You should handle it by checking each element of the list whether it's an atom. If so, check if it's equal to 'a', else, it's probably a list, call "memberDepth" recursively.
More about atom here
memberDepth(X,[L|Ls],Depth) :-
atom(L),!, % true iff L is an atom
...
memberDepth(X,[L|Ls],Depth) :-
...