I am trying to write a predicate which reverses all rows in a matrix using Prolog.
For instance the matrix [ [1,2,3], [4,5,6], [7,8,9] ] should become [ [3,2,1], [6,5,4], [9,8,7] ].
My attempt so far is :
reverseRows([[H|T]|_],X):-reverse([H|T],X).
which reverses only the first row. How can I change the above to work for all rows ? Any assistance is welcome.
The simplest solution is to use the predicate maplist/3.
?- maplist(reverse, [[1,2,3], [4,5,6], [7,8,9]], Reversed).
Reversed = [[3, 2, 1], [6, 5, 4], [9, 8, 7]].
Other possible solution is:
reverse_rows([], []).
reverse_rows([Xs|Xss], [Ys|Yss]) :-
reverse(Xs, Ys),
reverse_rows(Xss, Yss).
Example:
?- reverse_rows([[1,2,3], [4,5,6], [7,8,9]], Reversed).
Reversed = [[3, 2, 1], [6, 5, 4], [9, 8, 7]].
Related
My problem is that I have a functor with the next structure:
something(Perms, New_perms) :-
bagof(New_perm, aux_something(Perms, New_perm), <New_perms>).
aux_something(Perms, New_perm) :-
member(Perm, Perms),
take_impossible(Perm, New_perms).
take_impossible(Perm_poss, New_perm) :-
Perm_poss = [Var, Perm],
bagof(P, member(P, Perm), subsumes_term(Var, P)), New_perms),
New_perm = [Var, New_perms].
This takes a list of elements of the form:
[[A, 2, C], [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]]
It returns the list of possible permutations:
[[A, 2, C], [[1, 2, 3], [3, 2, 1]]]
But with the list containing an impossible element:
[[A, 4, C], [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]]
The functor should return false.
I need that, when it takes an element of the list which has no possible permutations, the list returns false. A forall instead of the bagof doesn't work because it doesn't change any variable bindings, and a forall before the bagof is too expensive, as I am doing the same operation to all elements of the list twice (it exceeds the limit time in the test). How can I break the execution of a bagof if the condition fails, or is there any other predicate that can do what I am looking for?
(Functor and aux_functor are not the real names of the variables, but this is college work, and so I am trying not to give too much info).
Stupid, question when I found the answer...
A bagof that fails when its objective fails is just a maplist.
Thanks for the help, anyway.
In this case, the correct answer would be:
something(Perms, New_perms) :-
maplist(take_impossible, Perms, New_perms).
take_impossible(Perm_poss, New_perm) :-
Perm_poss = [Var, Perm],
bagof(P, member(P, Perm), subsumes_term(Var, P)), New_perms),
New_perm = [Var, New_perms].
I am generating permutations:
takeout(X,[X|T],T).
takeout(X,[F|R],[F|S]):-
takeout(X,R,S).
perm([],[]).
perm([X|Y],Z):-
perm(Y,W),
takeout(X,Z,W).
I want to know how to create a list of all the permutations without using findall.
Example:
?-perm([1,2,3],List).
List = [[1, 2, 3], [2, 1, 3], [2, 3, 1], [1, 3, 2], [3, 1, 2], [3, 2, 1]]
Group permutations by the element it starts with.
Take an element X and create permutations Ys1 without it in the original list.
Adding this element X as the first element of all these permutations we have the list XP of permutations starting with X.
Appending all the groups will give you all permutations.
cons(X, Xs, [X|Xs]).
perm([], [[]]).
perm(Xs, Ys) :-
dif(Xs, []),
maplist({Xs}/[X, XP]>>(select(X, Xs, Xs1),
perm(Xs1, Ys1),
maplist(cons(X), Ys1, XP)),
Xs, Yss),
append(Yss, Ys).
?- perm([1, 2, 3], X).
X = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] ;
false.
?- length(Y, 8), perm(Y, X), length(X, N). %8 factorial
N = 40320
The idea is to generate permutations and test if you already created this permutation. I'm using the inbuild predicate permutation/2.
perm(Ori,Out):-
perm(Ori,[],Out).
perm(Ori,Acc,Ret):-
permutation(Ori,Perm),
\+ member(Perm,Acc),
!,
perm(Ori,[Perm|Acc],Ret).
perm(_,L,L).
?- perm([1,2,3],E).
E = [[3, 2, 1], [3, 1, 2], [2, 3, 1], [2, 1, 3], [1, 3, 2], [1, 2, 3]].
The code is not the fastest one since it checks multiple times for membership.
Let us consider lists such as L=[[7,3,4],9,[4,5],[1,3,5],4] where components could be lists or atoms. How to produce this type of permutation results:
R = [[7, 3, 4], 9, [4, 5], [1, 3, 5], 4]
R = [[7, 4, 3], 9, [5, 4], [1, 3, 5], 4]
R = [[7, 4, 3], 9, [4, 5], [1, 5, 3], 4]
....
In fact, we would like to have all the possible permutations of the sub-lists of L while the atom should remain unchanged.
I wrote a classical predicate permutation(OriginalList,PermutedList), and an allperm predicate that apply the maplist function to this permutation predicate:
permutation([],[]).
permutation(L,[T|Q]) :-
select(T,L,L1),
permutation(L1,Q).
/*L is the list to permute, R the result*/
allperm(L,R) :-
maplist(permutation,L,R).
It functions only in the special case where L is composed of lists and doesn't function when L is heterogeneous (atoms and lists).
Could you provide hints or elements of solution to do the right permutation?
The following modification should do:
permutation(X,X).
permutation(L,[T|Q]) :-
dif(L,[T|Q]),
select(T,L,L1),
permutation(L1,Q).
allperm(L,R) :-
maplist(permutation,L,R).
We extend the “identity” permutation to any Prolog term (first clause of permutation) and disallow it in the second clause (which can only be applied to lists anyway).
There is a simple Prolog insertion sort alghoritm:
sorting([A|B], Sorted) :- sorting(B, SortedTail), insert(A, SortedTail, Sorted).
sorting([], []).
insert(A, [B|C], [B|D]) :- A #> B, !, insert(A, C, D).
insert(A, C, [A|C]).
It does well on normal lists:
?- sorting([5, 4, 9, 1, 3, 8], X).
X = [1, 3, 4, 5, 8, 9].
But I also need to sort sublist of list contains any of them:
?- sorting([2, 5, [5, 4, 3], [6, 3], 4, 8], X).
X = [2, 4, 5, 8, [5, 4, 3], [6, 3]].
Is what return now. And
?- sorting([2, 5, [5, 4, 3], [6, 3], 4, 8], X).
X = [2, 4, 5, 8, [3, 4, 5], [3, 6]].
what I need to return. So how can I sort sublist too? Thanks in advance!
I offer this simple solution:
Insert element in the sorted list
insert(X, [], [X]):- !.
insert(X, [X1|L1], [X, X1|L1]):- X=<X1, !.
insert(X, [X1|L1], [X1|L]):- insert(X, L1, L).
Use principe of insertion sort algorithm
insertionSort([], []):- !.
insertionSort([X|L], S):- insertionSort(L, S1), insert(X, S1, S).
I need to find the combinations in a list of lists.
For example give the following list,
List = [[1, 2], [1, 2, 3]]
These should be the output,
Comb = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]
Another example:
List = [[1,2],[1,2],[1,2,3]]
Comb = [[1,1,1],[1,1,2],[1,1,3],[1,2,1],[1,2,2],[1,2,3]....etc]
I know how to do it for a list with two sublists but it needs to work for any number of sublists.
I'm new to prolog, please help.
try([],[]).
try([L|Ls],[M|Ms]):-
member(M,L),
try(Ls,Ms).
all(L,All) :- findall(M, try(L,M), All).
try returns one list composed of elements of the sublists of the first argument. all finds all such lists.
Here is your answer, cut and dry, as a fellow new prolog programmer myself.
%elementInList(input list, output answer)
answer(ListOfList, AnswerInList) :-
findall(Ans, combList(ListOfList, Ans), AnswerInList).
%combList(ListOfList, Comb) :-
combList([], []).
combList([Head|Tail], Comb) :-
combList(Tail, [Element|Tempcomb]),
elementInList(Head, Element).
%elementInList(List, Element)
elementInList([Head|_], Head).
elementInList([Head|Tail], Element) :-
elementInList(Tail, Element).
Using the definition answer(InputList, OutputResult), where e.g.
answer([[1,2],[7,8]],Comb).
Comb = [[1, 7], [2, 7], [1, 8], [2, 8]].
and e.g.
answer([[1,2],[2,8],[3,6,9]],Comb).
Comb = [[1, 2, 3], [2, 2, 3], [1, 8, 3], [2, 8, 3], [1, 2, 6], [2, 2, 6], [1, 8|...], [2|...], [...|...]|...].
and so on [X,Y,Z,..] for any number of sublists. You're welcome.