Related
I'm new to Prolog and I am having trouble with recursion and nested lists.
I want a predicate called getCommon(Number, List, X) which does the following:
getCommon(2, [[2,3], [2,5], [3,5]], X).
X = [[2,3], [2,5]].
I tried this but it returns an empty list and I am very confused as to why:
getCommon(_,[],_).
getCommon(Elem, [PointsH|PointsT], CommonPoints):-
nth0(0, PointsH, CurrElem),
(CurrElem = Elem -> append(CommonPoints,[PointsH],NewCommonPoints) ;append(CommonPoints,[],NewCommonPoints)),
getCommon(Elem, PointsT, NewCommonPoints).
Your code does not work because the recursion base case is not well defined and also because predicate append/3 is not properly used. Try the following code:
get_common(_, [], []).
get_common(K, [[K,Y]|Points], [[K,Y]|Rest]) :-
get_common(K, Points, Rest).
get_common(K, [[X,_]|Points], Rest) :-
dif(K,X),
get_common(K, Points, Rest).
Examples:
?- get_common(2, [[2,3], [3,2], [2,5], [3,7]], Common).
Common = [[2, 3], [2, 5]] ;
false.
?- get_common(3, [[2,3], [3,2], [2,5], [3,7]], Common).
Common = [[3, 2], [3, 7]] ;
false.
?- get_common(2, [[2,3], [K,2], [2,5], [3,7]], Common).
K = 2,
Common = [[2, 3], [2, 2], [2, 5]] ;
Common = [[2, 3], [2, 5]],
dif(K, 2) ;
false.
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 am really sorry for previous question, it's my first time post question on this website and I really didn't know I shouldn't post quesion like that.
It was my first time using prolog. Actually I spent more than 5 hours on this question but still cannot fully solve it, I tried to tear this question apart and here is what remain to be solved:
How to put the successive increasing whole numbers into a sublist in origin list.
eg. [3,5,1,2,3,7,8,2] to [3,5,[1,2,3],[7,8],2]
Here is what I wrote, can someone tell me how to fix the code? Thanks.
% empty List
chop_up([], []).
% single item list
chop_up([X], [X]).
% continue if the first number is not part of a sequence
chop_up(List, NewList):-
List = [First | Tail],
Tail = [Second | _],
First =\= Second - 1,
chop_up(Tail, NewList2),
NewList = [First | NewList2].
% if it is part of a sequence
chop_up(List, NewList):-
List = [First | Tail],
Tail = [Second | Tail2],
First is Second - 1,
chop_up(Tail, NewList2),
NewList = [[First] | NewList2].
enter image description here
Thank you for updating your question to show us what you tried!
Like all Prolog beginners, you are trying to do too much at once. This is normal! But you have to learn and get used to a way of thinking that is different from other programming languages. Almost always you have to decompose your problem into several subproblems that you then put together to get the final program.
So let's try to solve only one part of the problem first: Given a nonempty list, decompose it into successive elements at the front and into all the remaining elements. That is, we want something like this:
?- list_successive_rest([1, 2, 4, 3], Succ, Rest).
Succ = [1, 2],
Rest = [4, 3] .
If we can write this definition, then we should be able to iterate over the Rest to chop it up further.
Here is a definition of list_successive_rest/3. Note how it follows the structure of your attempt for chop_up/2, but it's shorter and simpler because we only look at a successive prefix of the list, not all of the list at once:
list_successive_rest([X], [X], []).
list_successive_rest([A, B | Xs], [A], [B | Xs]) :-
A + 1 =\= B.
list_successive_rest([A, B | Xs], [A | Successive], Rest) :-
A + 1 =:= B,
list_successive_rest([B | Xs], Successive, Rest).
(This is also simpler than your version because I match lists of at least two elements as [A, B | Xs] rather than [A | Tail] and Tail = [B | Tail2]. It's a good idea to get used to this syntax.)
We can call this successively to decompose a list into successive parts:
?- list_successive_rest([1, 2, 4, 3], Succ, Rest), list_successive_rest(Rest, Succ2, Rest2), list_successive_rest(Rest2, Succ3, Rest3).
Succ = [1, 2],
Rest = [4, 3],
Succ2 = [4],
Rest2 = Succ3, Succ3 = [3],
Rest3 = [] ;
false.
Defining chop_up/2 is now easy by using the above predicate to peel off successive prefixes of the list iteratively:
chop_up([], []).
chop_up(List, [Succ | Chopped]) :-
list_successive_rest(List, Succ, Rest),
chop_up(Rest, Chopped).
Note that chop_up/2 is recursive, and it uses list_successive_rest/3, which is recursive as well. Trying to write all this in one recursive predicate would be harder and lead to less readable code.
Let's try the above test, and your test case:
?- chop_up([1, 2, 4, 3], Chopped).
Chopped = [[1, 2], [4], [3]] ;
false.
?- chop_up([3,5,1,2,3,7,8,2], Chopped).
Chopped = [[3], [5], [1, 2, 3], [7, 8], [2]] ;
false.
This doesn't actually produce the exact format you wanted: Singleton elements are singleton lists rather than "naked" members of the outer list. I think this is better this way, but your teacher may disagree. In that case, changing this small detail is an exercise for you.
I conseived much more elegant way with DCG!
chunk_list([])-->[].
chunk_list([C|Rest])-->chunk(C),chunk_list(Rest).
chunk(Ret)-->[First],consecutive(First,Last),{First=:=Last->Ret is First;Ret = [First,Last]}.
consecutive(Prev,Last)-->[Current],{Current is Prev+1},consecutive(Current,Last).
consecutive(Prev,Prev)-->[].
Test:
?- phrase(chunk_list(R),[1,2,3,6,7,3,3,2,3,4,6],[]).
R = [[1, 3], [6, 7], 3, 3, [2, 4], 6]
maybe it could be reversible with more lavor.
I.E. convert [[1, 3], [6, 7], 3, 3, [2, 4], 6] into [1,2,3,6,7,3,3,2,3,4,6]
I also tried for my prolog training.
terrible program but does work anyway.
I tested this in ECLiPSe but it will work with few modification in other environment(may be only deleting :-lib(listut))
call like this:
chunk([4,5,6,3,4,4,57,3,4,5,7,2,3,4,5,7,7,54,3],Ret).
Program:
:-lib(listut).
chunk(List,Ans):-
chunk_sub(List,0,[],List1),
first_and_lasts(List1,Ans),
!.
chunk_sub([],_,Ret,Reverse):-reverse(Ret,Reverse),!.
chunk_sub([Current|Rest],Prev,[NowList|RetRest],Ret):-
Current =:= Prev+1,
append(NowList,[Current],NextList),
chunk_sub(Rest,Current,[NextList|RetRest],Ret).
chunk_sub([Current|Rest],_,NowList,Ret):-
chunk_sub(Rest,Current,[[Current]|NowList],Ret).
first_and_lasts([],[]):-!.
first_and_lasts([FirstList|RestLists],[Converted|RestRet]):-
length(FirstList,Len),
(
Len=:=1->
([OneElem]=FirstList,Converted=OneElem);
(
nth1(1,FirstList,Smallest),
nth1(Len,FirstList,Biggest),
Converted=[Smallest,Biggest]
)
),
first_and_lasts(RestLists,RestRet).
Finally I did it!
this is reversible(generalized) version.This program works cleverly.
It was very fun developing this.
Code:
chunk_list([])-->[],!.
chunk_list([Chunk|Rest])-->chunk(Chunk),!,chunk_list(Rest).
chunk([First,Last])-->sequence([First,Last]),{First<Last}. % sequence
chunk(Val)-->sequence([Val,Val]). % isolated number
sequence([First,Last])-->
{(number(First),number(Last))->First<Last;true},
[First],
{succ(First,Second)},sequence([Second,Last]).
sequence([Val,Val])-->[Val].
Test:
[eclipse 4]: phrase(chunk_list([2,[2,6],[3,5],3,7,[1,3]]),Ret).
Ret = [2, 2, 3, 4, 5, 6, 3, 4, 5, 3, 7, 1, 2, 3]
Yes (0.00s cpu)
[eclipse 5]: phrase(chunk_list(Ret),[3,4,5,2,1,6,7,88,9,4,5,6,7,2,1,2,3]).
Ret = [[3, 5], 2, 1, [6, 7], 88, 9, [4, 7], 2, [1, 3]]
Yes (0.00s cpu)
[eclipse 6]: phrase(chunk_list([[2,4],A,[2,8],3]),[2,B,4,6,2,C,4,5,6,7,D,E]).
A = 6
B = 3
C = 3
D = 8
E = 3
Yes (0.00s cpu)
I am trying to make a list*list of all permutations from 1 to N
Example: perm(3, X). -> X = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
I am instead getting
X = [1, 2, 3]
X = [1, 3, 2]
X = [2, 1, 3]
X = [2, 3, 1]
X = [3, 1, 2]
X = [3, 2, 1]
and having to keep hitting next. My question is how would I put all values of X into a list like the example run that I want. Here is my existing code:
permHelp([],[]).
permHelp(List,[H|Finish]):-delete(H,List,Rest),permHelp(Rest,Finish).
delete(X,[X|T],T).
delete(X,[H|T],[H|NT]):-delete(X,T,NT).
createList(0, L, L) :- !.
createList(N, R, L) :- N > 0, N1 is N-1, createList(N1, [N|R], L).
perm(N, X):- createList(N, [], L), permHelp(L, X).
perm(N, X):-
createList(N, [], L),
list_allperms(L, X).
With list_allperms/2 defined in another answer.
What you call permHelp should rather be called permutation.
I'm trying to write a predicate that divides a list into N parts.
This is what I have so far.
partition(1, List, List).
partition(N, List, [X,Y|Rest]):-
chop(List, X, Y),
member(NextToChop, [X,Y]), %Choose one of the new parts to chop further.
NewN is N-1,
partition(NewN, NextToChop, Rest).
chop(List, _, _):-
length(List, Length),
Length < 2, %You can't chop something that doesn't have at least 2 elements
fail,!.
chop(List, Deel1, Deel2):-
append(Deel1, Deel2, List),
Deel1 \= [],
Deel2 \= [].
The idea is to keep chopping parts of the list into two other parts until I have N pieces.
I have mediocre results with this approach:
?- partition(2, [1,2,3,4], List).
List = [[1], [2, 3, 4], 1] ;
List = [[1], [2, 3, 4], 2, 3, 4] ;
List = [[1, 2], [3, 4], 1, 2] ;
List = [[1, 2], [3, 4], 3, 4] ;
List = [[1, 2, 3], [4], 1, 2, 3] ;
List = [[1, 2, 3], [4], 4] ;
false.
So I get what I want, but I get it two times and there are some other things attached.
When dividing into 3 parts things get worse:
?- partition(3, [1,2,3,4], List).
List = [[1], [2, 3, 4], [2], [3, 4], 2] ;
List = [[1], [2, 3, 4], [2], [3, 4], 3, 4] ;
List = [[1], [2, 3, 4], [2, 3], [4], 2, 3] ;
List = [[1], [2, 3, 4], [2, 3], [4], 4] ;
List = [[1, 2], [3, 4], [1], [2], 1] ;
List = [[1, 2], [3, 4], [1], [2], 2] ;
List = [[1, 2], [3, 4], [3], [4], 3] ;
List = [[1, 2], [3, 4], [3], [4], 4] ;
List = [[1, 2, 3], [4], [1], [2, 3], 1] ;
List = [[1, 2, 3], [4], [1], [2, 3], 2, 3] ;
List = [[1, 2, 3], [4], [1, 2], [3], 1, 2] ;
List = [[1, 2, 3], [4], [1, 2], [3], 3] ;
false.
Another idea is using prefix but I don't know how that would really work. To use that I should be able to let Prolog know that it needs to take a prefix that's not too short and not too long either, so I don't take a prefix that's too long so there's nothing left for a next recursion step.
Can anyone point me in the right direction?
Little clarification: the predicate should return all posibilities of dividing the list in N parts (not including empty lists).
When describing relations that involve lists, DCGs are often very useful. Consider:
list_n_parts(List, N, Parts) :-
length(Parts, N),
phrase(parts(Parts), List).
parts([]) --> [].
parts([Part|Parts]) --> part(Part), parts(Parts).
part([P|Ps]) --> [P], list(Ps).
list([]) --> [].
list([L|Ls]) --> [L], list(Ls).
Sample query:
?- list_n_parts([1,2,3,4], 2, Ps).
Ps = [[1], [2, 3, 4]] ;
Ps = [[1, 2], [3, 4]] ;
Ps = [[1, 2, 3], [4]] ;
false.
Here is the basic way I'd use to implement that (using append/2 and length/2) :
list_n_parts(List, Parts, Result) :-
length(Result, Parts),
append(Result, List).
Now, that doesn't totally complies to your expectations : it allows for [].
One idea to fix that is to use a maplist call to format the Resulting list beforehand :
list_n_parts(List, Parts, Result) :-
length(Result, Parts),
using copy_term/2, the maplist/2 call looks like :
maplist(copy_term([_|_]), Result),
using functor/3 (credits to #false), it would look like :
maplist(functor('.', 2), Result),
using lambda.pl you could write :
maplist(\[_|_]^true, Result),
since the '\' already performs a term copy (thanks #false).
The only thing left is the append/2 call:
append(Result, List).
Another idea would be to use forall/2 filtering (maybe simpler to get, but worse in complexity) :
list_n_parts(List, Parts, Result) :-
length(Result, Parts),
append(Result, List),
forall(member(X, Result), X \= []).
etc...