How to add multiple heads to a list using recursion - list

I want to remove every nth element from both list A and B that doesn't correspond with each other's nth element. So for example: I have list A containing [1,2,3,4,5] and list B containing [1,2,2,4,7]. The result should be list C containing [3,5] and list D containing [2,7]. I came up with this little piece of code, but it isn't working properly yet.
without_doubles([], [], [_], [_]).
without_doubles([H|T1], [H|T2], C, D):-
without_doubles(T1, T2, C, D).
without_doubles([H1|T1], [H2|T2], [H1|C], [H2|D]):-
without_doubles(T1, T2, C, D).
Instead of the [3,5] and [2,7], I'm getting [3,5,_G2442] and [2,7,_G2445]. I know it's probably easy to fix, but I can't seem to figure it out. Thanks for helping me in advance!

Your first rule should be:
without_doubles([], [], [], []).
the two anonymous variables _ that you had before were the cause of your problem.
There is however a second problem with your code:
?- without_doubles([1,2,3,4,5],[1,2,2,4,7],L,R).
L = [3, 5],
R = [2, 7] ;
L = [3, 4, 5],
R = [2, 4, 7] ;
L = [2, 3, 5],
R = [2, 2, 7] ;
L = [2, 3, 4, 5],
R = [2, 2, 4, 7] ;
L = [1, 3, 5],
R = [1, 2, 7] ;
L = [1, 3, 4, 5],
R = [1, 2, 4, 7] ;
L = [1, 2, 3, 5],
R = [1, 2, 2, 7] ;
L = [1, 2, 3, 4, 5],
R = [1, 2, 2, 4, 7].
Obviously we only want the first result, not the other ones. The reason why we get the other ones is because at no point do you state in your last rule that H1 and H2 should be different. This means that when Prolog can apply the second rule, it will also be able to apply the last rule and thus create all those choice points.
You can fix this by explicitely stating that H1 and H2 must be different in your last rule, using dif/2:
without_doubles([H1|T1], [H2|T2], [H1|C], [H2|D]):-
dif(H1, H2),
without_doubles(T1, T2, C, D).
Now we have:
?- without_doubles([1,2,3,4,5],[1,2,2,4,7],L,R).
L = [3, 5],
R = [2, 7] ;
false.

There are two problems with your code:
the basecase specifies singleton lists as third and fourth argument, whereas these should be empty lists;
nothing is preventing you from backtracking over the second clause, and thus take the third clause.
You can fix this as follows:
%% no [_], but []
without_doubles([], [], [], []).
without_doubles([H|T1], [H|T2], C, D):-
without_doubles(T1, T2, C, D).
%% guard the fact that H1 and H2 are different
without_doubles([H1|T1], [H2|T2], [H1|C], [H2|D]):-
dif(H1,H2),
without_doubles(T1, T2, C, D).

Related

Prolog: Comparing Lists from Lists of Lists

I am now quite a while trying to figure out what my mistake is, but I am not able to.
Task:
We have to figure out how to find three permutations of a List containing 9 elements in the form of List of Lists. Each List of Lists should contain three sublists, each containing three elements. But no element is allowed to be together with another element in two different sublists.
The following output for the three permutations A, B, C with the given List= [1,2,3,4,5,6,7,8,9] could be:
predicate(A, B, C , [1,2,3,4,5,6,7,8,9]).
A = [[1,2,3],[4,5,6],[7,8,9]],
B = [[1,4,7],[2,5,8],[3,6,9]],
C = [[1,5,9],[2,6,7],[3,4,8]].
My Code so far (first my helper predicates) :
To split a list into a List of Lists ( N is always 3 ):
split_list(List, N, Splitted_List) :-
split_helper(List, N, [], Splitted_List).
split_helper([], _, Acc, Acc).
split_helper(List, N, Acc, Splitted_List) :-
my_append(H, T, List),
my_length(H, N),
split_helper(T, N, [H|Acc], Splitted_List).
A possible query:
split_list([1,2,3,4,5,6,7,8,9], 3, X).
X = [[1,2,3],[4,5,6],[7,8,9]].
To check wether all sublists of a List of lists contains at most one same element:
max_one_common_element(List1, List2) :-
max_one_common_element(List1, List2, 0).
max_one_common_element([], _, Count) :-
Count =< 1.
max_one_common_element([H|T], List2, Count) :-
(my_member(H, List2) ->
NewCount is Count + 1,
max_one_common_element(T, List2, NewCount)
;
max_one_common_element(T, List2, Count)
).
A possible query:
max_one_common_element([[1,2,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]]).
True.
To change order of sublists, for comparing purposes (important later on):
swap_lists(List, Result):-
select(Selected, List, Rest),
append(Rest, [Selected], Result).
A possible query:
swap_list([[1,2,3],[4,5,6],[7,8,9]], X).
X = [[4,5,6],[7,8,9],[1,2,3]].
My main predicate, which instantiates A, B and C. The one making me issues is C, A and B are properly instantiated.
I was thinking to take all permutations of the input List and check with max_one_common_element/2 wether each sublists has at most one common element.
Since max_one_common_element/2 is only able to check both lists at the current index ( e.g. [[1,2],[3,4]], [[3,4],[1,2]] would return True, even though it is False) my idea was to change the order of the sublists from A and B two times and check again with C after the first and second change, so all 3 sublists of A and B should be covered.
main_predicate(A, B, C, List):-
/* instantiates A as the input list but seqmented */
split_list(List, 3 , A),
/* instantiates B as a permutation of A, taking every nth element in a sublist*/
%This part is unimportant since it works properly
/* instantiates C as a permutation from the input list, test that each Sub-List contains at most one same element */
permutation(List, Permuted),
split_list(Permuted, Size, Dessert),
max_one_common_element(A, C),
max_one_common_element(A, C),
/* first swap A and B two times */
swap_lists(A, A1),
swap_lists(A1, A2),
swap_lists(B, B1),
swap_lists(B1, B2),
/* Check again with C */
max_one_common_element(A1, C),
max_one_common_element(A2, C),
max_one_common_element(B1, C),
max_one_common_element(B2, C).
When I make a query of:
predicate(A, B ,C, [1,2,3,4,5,6,7,8,9] ).
My output is:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ,
B = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] ,
C = [[7, 8, 9], [4, 5, 6], [1, 2, 3]] .
Prolog just do not seem to consider every call of max_one_common_element/2. Since deleting some seem to change the output, but in my mind I have considered all cases and everything should be fine. I also considered changing max_one_common_element/2, but nothing works.
Thank you really much for your help in advance.
Controlling the backtracking was interesting (to enforce comb_available over all the solution sublists):
:- dynamic used/2.
list_perm3(SubLen, L, P) :-
length(L, Len),
int_div_lt_plus1(Len, SubLen, SegLen),
retractall(used(_, _)),
% Work with instantiated, unique list
int_list_wrap(L, LN),
list_perm3_loop(LN, SubLen, SegLen, PN),
% Map to elements in original list
perm_lists_wrap(PN, L, P).
int_list_wrap(L, LN) :-
int_list_wrap_(L, 1, LN).
int_list_wrap_([], _, []).
int_list_wrap_([H|T], I, [i(I, H)|LN]) :-
I1 is I + 1,
int_list_wrap_(T, I1, LN).
% Can contain sublists
perm_lists_wrap([], _, []).
perm_lists_wrap([[]|T], L, [[]|P]) :-
perm_lists_wrap(T, L, P).
perm_lists_wrap([[H|R]|T], L, [E|P]) :-
% Is a sublist
perm_lists_wrap([H|R], L, E),
perm_lists_wrap(T, L, P).
% Using i/2 for first-argument indexing
perm_lists_wrap([i(_, E)|T], L, [E|P]) :-
perm_lists_wrap(T, L, P).
int_div_lt_plus1(Int, Div, Mod) :-
divmod(Int, Div, Mod0, Rem),
( Rem =:= 0
-> Mod is Mod0
% If doesn't divide cleanly, add 1
; Mod is Mod0 + 1
).
list_perm3_loop(L, SubLen, SegLen, P) :-
% Keeping backtracking to this top-level
(list_perm3_(L, SubLen, SegLen, P) -> true ; !, fail).
list_perm3_loop(L, SubLen, SegLen, P) :-
list_perm3_loop(L, SubLen, SegLen, P).
list_perm3_(L, SubLen, SegLen, P) :-
length(P, SegLen),
perm3_segments(P, SubLen, L),
assert_used(P).
assert_used([]).
assert_used([H|T]) :-
% Assert the used pairs, to prevent reuse
forall(
( select(E1, H, H0),
member(E2, H0)
),
assert(used(E1, E2))
),
assert_used(T).
perm3_segments([], _, []).
perm3_segments([H|T], SubLen, L) :-
perm3(L, H, SubLen, R),
perm3_segments(T, SubLen, R).
perm3(L, P, SubLen, R) :-
length(L, LLen),
PLen is min(LLen, SubLen),
length(P, PLen),
perm3_(P, L, [], R).
perm3_([], R, _, R).
perm3_([H|T], L, P, R) :-
select(H, L, L0),
comb_available(P, H),
perm3_(T, L0, [H|P], R).
comb_available([], _).
comb_available([H|T], E) :-
\+ used(E, H),
comb_available(T, E).
Results in swi-prolog:
?- list_perm3(3, [1,2,3,4,5,6,7,8,9], P).
P = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ;
P = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] ;
P = [[1, 5, 9], [2, 6, 7], [3, 4, 8]] ;
P = [[1, 6, 8], [2, 4, 9], [3, 5, 7]] ;
false.
To take the first 3:
?- once(findnsols(3, P, list_perm3(3, [1,2,3,4,5,6,7,8,9], P), [A,B,C])).
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
B = [[1, 4, 7], [2, 5, 8], [3, 6, 9]],
C = [[1, 5, 9], [2, 6, 7], [3, 4, 8]].
Example of handling vars and leftover sublists:
?- list_perm3(3, [1,2,3,Four,5,6,7,8,9,Ten,Eleven], P).
P = [[1, 2, 3], [Four, 5, 6], [7, 8, 9], [Ten, Eleven]] ;
P = [[1, Four, 7], [2, 5, 8], [3, 6, Ten], [9, Eleven]] ;
P = [[1, 5, 9], [2, Four, Ten], [3, 7, Eleven], [6, 8]] ;
P = [[1, 6, Eleven], [3, Four, 8], [5, 7, Ten], [2, 9]] ;
false.
I managed to come up with my own solution:
make_dessert(Starter, Main, Dessert, List_of_Persons, Size):-
permutation(List_of_Persons, Permuted),
split_list(Permuted, Size, Dessert),
at_most_one_common(Starter, Dessert),
at_most_one_common(Main, Dessert).
split_list(List, N, Splitted_List) :-
split_helper(List, N, [], Splitted_List).
split_helper([], _, Acc, Acc).
split_helper(List, N, Acc, Splitted_List) :-
append(H, T, List),
length(H, N),
split_helper(T, N, [H|Acc], Splitted_List).
at_most_one_common([], _).
at_most_one_common([H|T], List2) :-
check_list(H, List2),
at_most_one_common(T, List2).
check_list(_, []).
check_list(X, [H|T]) :-
intersection(X, H, Z),
length(Z, L),
L =< 1,
check_list(X, T).
I forgot to mention that I receive bonus points for keeping the inferences as low as possible. As my program is not as efficient as #brebs 's, I would really appreciate a few tipps from you to lower these. I am maybe also considering starting a new question regarding this case later on.

Prolog - Creating a list of all the possible shifts of another list?

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.

Prolog: Generating Every Possibility of a List Given a Pattern

Let's say you have a list in Prolog such as: [3,4,2,2,1,4]. How would one go about generating a list of lists of all possible patterns that start at the first element of the list, then either go to the i + 2th element, or the i + 3rd element, and so on from there.
Example:
Say I have [3,4,2,2,1,4,8].
I want to be able to generate a list of lists such as:
[[3,2,1,8], [3,2,4], [3,2,8]]
I.e. all possibilities of either every other element or every i+3 element, or any other combination, such as i+2,i+3,i+2,i+2, etc.
I've implemented my own version of a powerset, but I can't seem to figure out where to start.
gen([], []).
gen([A], [A]).
gen([A, _ | T], [A | Xs]) :- gen(T, Xs).
gen([A, _, _ | T], [A | Xs]) :- gen(T, Xs).
results in
?- gen([3,4,2,2,1,4,8], X).
X = [3, 2, 1, 8] ;
X = [3, 2, 1] ;
X = [3, 2, 4] ;
X = [3, 2, 4] ;
X = [3, 2, 8] ;
false.
You can use findall/3 to get all results
?- findall(X, gen([3,4,2,2,1,4,8], X), Z).
Z = [[3, 2, 1, 8], [3, 2, 1], [3, 2, 4], [3, 2, 4], [3, 2, 8]].

Prolog how do I append a list of lists into one list?

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]] ...

Prolog - dividing a list in N parts

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...