How to divide unordered set into subsets in Prolog - list

I need a predicate that splits a given set into subsets
What I have so far:
divide_set(S, Sd) :-
length(S, L),
between(1, L, N),
length(Sd, N),
append(Sd, S),
forall(member(M, Sd), M \= []).
Which gives me these results:
?- divide_set([a, b, c, d, e, f], Sd).
Sd = [[a, b, c, d, e, f]] ;
Sd = [[a], [b, c, d, e, f]] ;
Sd = [[a, b], [c, d, e, f]] ;
Sd = [[a, b, c], [d, e, f]] ;
Sd = [[a, b, c, d], [e, f]] ;
Sd = [[a, b, c, d, e], [f]] ;
...
So the set is treated as an ordered set however I want [a, f] for instance to be included too.
How can I extend my predicate so that I get subsets rather than subsquences?
(I could do it for every possible sequence, but I think that'd not be the best solution)

Wow, kind of a tricky problem! My first thought was to try something like this, a declarative reading:
superset(Superset, Subsets) :-
foreach(member(Subset, Subsets),
foreach(member(X, Subset), member(X, Superset))).
This looks good on paper, but using member/2 to generate leads to infinite recursion as it hallucinates massive lists that contain unbound variables. So that didn't work.
My next thought was, maybe I could just generate all permutations like you suggested. But as I imagined generating all the permutations and then building all possible lists around them, it started to sound like there would be a lot of repeated answers. So I came around to your opinion, that there is probably a more efficient way to do this.
Then I started out by making some example input/outputs, which looked like this:
divide_set([X,Y], [[X],[Y]]).
divide_set([X,Y], [[X,Y]]).
divide_set([X,Y,Z], [[X],[Y],[Z]]).
divide_set([X,Y,Z], [[X],[Y,Z]]).
divide_set([X,Y,Z], [[X,Y],[Z]]).
divide_set([X,Y,Z], [[X,Z],[Y]]).
divide_set([X,Y,Z], [[X,Y,Z]]).
Grouping them in this way helped me see an approach: one in which I either pull out the front item and recur, or pull out the front item and prepend it to the recursive result, which led me to this implementation:
divide_set([X], [[X]]).
divide_set([X|Remainder], [[X]|Rest]) :-
divide_set(Remainder, Rest).
divide_set([X|Remainder], [[X|Subset]|RestButOne]) :-
divide_set(Remainder, Rest),
select(Subset, Rest, RestButOne).
I don't know for sure if this is right, but this is the output I get on your sample input:
?- divide_set([1,2,3,4], X).
X = [[1], [2], [3], [4]] ;
X = [[1], [2], [3, 4]] ;
X = [[1], [2, 3], [4]] ;
X = [[1], [2, 4], [3]] ;
X = [[1], [2, 3, 4]] ;
X = [[1, 2], [3], [4]] ;
X = [[1, 3], [2], [4]] ;
X = [[1, 4], [2], [3]] ;
X = [[1, 2], [3, 4]] ;
X = [[1, 3, 4], [2]] ;
X = [[1, 2, 3], [4]] ;
X = [[1, 4], [2, 3]] ;
X = [[1, 2, 4], [3]] ;
X = [[1, 3], [2, 4]] ;
X = [[1, 2, 3, 4]] ;
false.
I haven't done the math to see what we should get in terms of answers combinatorically, but at first blush this looks right to me. I see all the different sizes of subset I'd expect with four elements, and I see all the different quantities of subsets I'd expect. The work does diminish as it gets further into the recursion; you'll notice the number 1 never appears in the second or subsequent lists, 2 never appears in the 3rd or 4th subsets, etc. So I think there are reasonable odds of this being correct.
Also, the scenario you are interested in does occur:
?- divide_set([a, b, c, d, e, f], [[a,f]|Rest]).
Rest = [[b], [c], [d], [e]] ;
Rest = [[b], [c], [d, e]] ;
Rest = [[b], [c, d], [e]] ;
Rest = [[b], [c, e], [d]] ;
Rest = [[b], [c, d, e]] ;
Rest = [[b, c], [d], [e]] ;
Rest = [[b, d], [c], [e]] ;
Rest = [[b, e], [c], [d]] ;
Rest = [[b, c], [d, e]] ;
Rest = [[b, d, e], [c]] ;
Rest = [[b, c, d], [e]] ;
Rest = [[b, e], [c, d]] ;
Rest = [[b, c, e], [d]] ;
Rest = [[b, d], [c, e]] ;
Rest = [[b, c, d, e]] ;
false.

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.

Set difference of two compatible lists in Prolog

I'm currently trying to implement an automated theorem prover in prolog and have stumbled across a problem.
If I have a list of lists such as:
[[1,2],[-1,3],[4,5,7],[-2,4]]
How would I get the "set difference" of two compatible list items:
What I mean by compatible is, if the negation of a certain number exists in another list, then replace those two lists with the set difference, ie:
[1,2] and [-1,3] are compatible because -1 is present in the second clause and thus it should return the set difference of [2,3] and the new list should be [[2,3],[4,5,7],[-2,4]].
Currently I have the following step predicate:
memberlist(X,[[X|_]|_]).
memberlist(X,[[_|T1]|T2]) :-
memberlist(X,[T1|T2]).
memberlist(X,[[]|T2]) :-
memberlist(X,T2).
step([]).
step([_|T]) :-
memberlist(neg X,T),
write(X),
nl,
step(T).
step([_|T]) :-
step(T).
So it simply checks each list and checks if the negation of a variable exists and if it does simply write it out. I've already added code which deals with negative numbers, so X will match a -X, X being any integer.
I'm quite stuck at this point, and any help would be greatly appreciated.
Another possible solution:
shrink([L1|R1], [L3|R2]) :-
select(L2, R1, R2),
difference(L1, L2, L3).
shrink([L1|R1], [L1|S]) :-
shrink(R1, S).
difference(L1, L2, L3) :-
select(X, L1, R1),
compatible(X, Y),
select(Y, L2, R2),
union(R1, R2, L3).
compatible(neg(P), P) :- !.
compatible(P, neg(P)).
Some examples:
?- shrink([[1,2], [neg(1),3], [4,5,6], [neg(2),4]], S).
S = [[2, 3], [4, 5, 6], [neg(2), 4]] ;
S = [[1, 4], [neg(1), 3], [4, 5, 6]] ;
false.
?- shrink([[a,neg(b)], [a,b]], S).
S = [[a]] ;
false.
?- shrink([[rainning], [neg(rainning)]], S).
S = [[]] ;
false.
?- shrink([[rainning], [neg(rainning), wet_grass], [neg(wet_grass), green_grass]], S).
S = [[wet_grass], [neg(wet_grass), green_grass]] ;
S = [[rainning], [neg(rainning), green_grass]] ;
false.
?- shrink([[neg(green_grass)], [rainning], [neg(rainning), wet_grass], [neg(wet_grass), green_grass]], A), shrink(A, B), shrink(B, C).
A = [[neg(wet_grass)], [rainning], [neg(rainning), wet_grass]],
B = [[neg(rainning)], [rainning]],
C = [[]] ;
A = [[neg(wet_grass)], [rainning], [neg(rainning), wet_grass]],
B = [[neg(wet_grass)], [wet_grass]],
C = [[]] ;
A = [[neg(green_grass)], [wet_grass], [neg(wet_grass), green_grass]],
B = [[neg(wet_grass)], [wet_grass]],
C = [[]] ;
A = [[neg(green_grass)], [wet_grass], [neg(wet_grass), green_grass]],
B = [[neg(green_grass)], [green_grass]],
C = [[]] ;
A = [[neg(green_grass)], [rainning], [neg(rainning), green_grass]],
B = [[neg(rainning)], [rainning]],
C = [[]] ;
A = [[neg(green_grass)], [rainning], [neg(rainning), green_grass]],
B = [[neg(green_grass)], [green_grass]],
C = [[]] ;
false.
An alternative formulation.
memberlist will give you the triples p(X, Y, Z) where Z and neg(Z) are in X and Y.
collapse will take such a triple and remove X, Y from Xs and add X+Y-Z-neg(Z) to it.
memberlist([X|Xs], p(X, Y, Z)) :-
member(Z, X), member(Y, Xs), member(neg(Z), Y).
memberlist([X|Xs], p(X, Y, Z)) :-
member(neg(Z), X), member(Y, Xs), member(Z, Y).
memberlist([_|Xs], A) :-
memberlist(Xs, A).
collapse(Xs, Ys) :-
memberlist(Xs, p(A, B, I)), % A and B have some I and neg(I) in them
select(A, Xs, XsA), % remove A
select(B, XsA, XsAB), % remove B
append(A, B, AB), select(I, AB, ABI), select(neg(I), ABI, ABII),
Ys = [ABII|XsAB].
Your example
?- collapse([[1, 2], [neg(1), 3], [4, 5, 7], [neg(2), 4]], X).
X = [[2, 3], [4, 5, 7], [neg(2), 4]] ;
X = [[1, 4], [neg(1), 3], [4, 5, 7]] ;
false.

how to make a list of lists with a certain width

i want to implement a function that make a list of sublists with a certain width. For example :
?- list_to_llists([w,w,w,w],2,LL). %1
LL = [[w, w], [w, w]] ;
false.
?- list_to_llists([w,w,c,l,r,w,c,c,w,w,w,w],3,LL). %2
LL = [[w, w, c], [l, r, w], [c, c, w], [w, w, w]] ;
false.
?- list_to_llists([w,w,w,w],3,LL). %3
LL = [[w, w, w]] ;
false.
sublist(I1,I2,L,Sub) :-
sublist2(I1,I2,L,[],Sub).
sublist2(I1,I2,L,Sub,Sub):-
length(Sub,N),
N\=0,
I1>I2.
sublist2(I1,I2,L,Sub,Sub2):-
I1<I2,
nth0(I1,L,X),
I3 is I1+1,
append(Sub,[X],Z),
sublist2(I3,I2,L,Z,Sub2).
sublist2(A,B,L,Sub,Sub2):-
B=A,
nth0(A,L,X),
NewA is A+1,
append(Sub,[X],Z),
sublist2(NewA,B,L,Z,Sub2).
list_to_llists(L,W,LLists):-
length(L,X),
X=<W,
LLists=[L].
list_to_llists2([],W,LLists,A):- LLists=A .
list_to_llists2(L,W,LLists,A):-
P is W-1 ,
sublist(0,P,L,Result),
append([Result],A,U),
append(Result,K,L),
list_to_llists2(K,W,LLists,U).
list_to_llists(L,W,F):-
list_to_llists2(L,W,R,[[]]).
but case 2 and 3 don't work at all
secondly, i want to implement a function that takes certain facts and put them in L where L is a list but i have to use list_to_lists to make L kind of list of lists list (it's a map)
for example (test cases):
?- length(L,100),ensure_hints(L, [at(3, 5, c), at(5, 0, w), at(9, 6, c)],10,10).
L = [_G1699, _G1702, _G1705, _G1708, _G1711, w, _G1717, _G1720, _G1723, _G1726,
_G1729, _G1732, _G1735, _G1738, _G1741, _G1744, _G1747, _G1750, _G1753, _G1756,
_G1759, _G1762, _G1765, _G1768, _G1771, _G1774, _G1777, _G1780, _G1783, _G1786,
_G1789, _G1792, _G1795, _G1798, _G1801, _G1804, _G1807, _G1810, _G1813, _G1816,
_G1819, _G1822, _G1825, _G1828, _G1831, _G1834, _G1837, _G1840, _G1843, _G1846,
_G1849, _G1852, _G1855, c, _G1861, _G1864, _G1867, _G1870, _G1873, _G1876,
_G1879,_G1882, _G1885, _G1888, _G1891, _G1894, _G1897, _G1900, _G1903, c,
_G1909, _G1912,_G1915, _G1918, _G1921, _G1924, _G1927, _G1930, _G1933, _G1936,
_G1939, _G1942, _G1945, _G1948, _G1951, _G1954, _G1957, _G1960, _G1963, _G1966,
_G1969,_G1972, _G1975, _G1978, _G1981, _G1984, _G1987, _G1990, _G1993, _G1996];
false
?- length(L,9),ensure_hints(L, [at(1, 2, c), at(0, 1, l)],3,3).
L = [_G1589, _G1592, _G1595, l, _G1601, _G1604, _G1607, c, _G1613] ;
false.
?- length(L,9),ensure_hints(L, [at(1, 2, c), at(0, 5, l)],3,3).
false.
but it doesn't work for me
my code :
ensure_hints(L,Hints,W,H):-
list_to_llists(L,W,C),
Hints=[H|T],
H=at(X,Y,O),
nth0(X,L,Z),
nth0(Y,Z,O),
ensure_hints(L,T,W,H).
Here is a simple solution:
list_to_llists(List, Len, [H|T]) :-
length(H, Len),
append(H, Rest, List),
!,
list_to_llists(Rest, Len, T).
list_to_llists(_, _, []).
It simple removes sublists of length Len until there is no complete sublist left (it seems you want to ignore incomplete sublists).
You can play with it on http://swish.swi-prolog.org/p/OqfzwRoe.pl

Why do i get unexpected answer in Prolog. List, multiply, recursion

I have to display all elements in lists as is shown in example.
Element: el, List: L. [L1el1, L2el1], [L1el2, L2el1], [L1el3, L2el1]...
I am using multiply/3 predecate to run program and multiply/4 for recursion. It restores 'L1' from 'Tmp' when it gets empty (only if L2 is not empty. Otherwise, terminate recursion).
Abstract example:
for element l in List1 {
for element k in List2 {
print([k, l]);
}
}
my_code.pl
multiply(L1, L2, X):-
multiply(L1, L2, L1, X).
multiply(X, [], _, X).
multiply([], [_|T], Tmp, X):-
multiply(Tmp, T, Tmp, X),!.
multiply([H|T], [H1|T1], Tmp, [[H,H1]|X]):-
multiply(T, [H1|T1], Tmp, X).
Expected:
?- multiply([1,2,3], [a,b], X).
X = [[1, a], [2, a], [3, a], [1, b], [2, b], [3, b]].
What did I get:
?- multiply([1,2,3], [a,b], X).
X = [[1, a], [2, a], [3, a], [1, b], [2, b], [3, b], 1, 2, 3].
How to get expected result modifying this code a bit. Without using built-in predicates!
Why L1 appears at the end of X? how to fix it?
The problem was in the multiply/4 with recursion exiting condition.
multiply(X, [_|X], _, X).

Prolog list problem

[a,b,c,d] and
[[1,2,3,4],[5,6,7,8],[43,34,56,5],[23,32,2,2]]
I want to make
[[a,1,2,3,4],[b,5,6,7,8],[c,43,34,56,5],[d,23,32,2,2]]
I use swi prolog is it possible do it ?
Thanks a lot.
solve([], [], []).
solve([[X|Y]|S], [X|L1], [Y|L2]):-
solve(S, L1, L2).
UPDATE: How to use
Write the function in a file "a.pl", then in swi-prolog type:
['a.pl'].
then type:
solve(X, [a,b,c,d], [[1,2,3,4],[5,6,7,8],[43,34,56,5],[23,32,2,2]]).
You will get:
X = [[a, 1, 2, 3, 4], [b, 5, 6, 7, 8], [c, 43, 34, 56, 5], [d, 23, 32, 2, 2]]
I have the strange feeling that I am doing your homework. Is it?
Use meta-predicate maplist/4 and Prolog lambdas like this:
?- As = [a,b,c,d],
Bss = [[1,2,3,4],[5,6,7,8],[43,34,56,5],[23,32,2,2]],
maplist(\H^T^[H|T]^true,As,Bss,Css).
As = [ a , b , c , d ],
Bss = [[ 1,2,3,4],[ 5,6,7,8],[ 43,34,56,5],[ 23,32,2,2]],
Css = [[a,1,2,3,4],[b,5,6,7,8],[c,43,34,56,5],[d,23,32,2,2]].
Edit
Different lambda terms can be used in above maplist/4 goal, as pointed out in a comment.
maplist(\H^T^[H|T]^true,As,Bss,Css)
maplist(\H^T^ =([H|T]) ,As,Bss,Css)
SWI Prolog can do this with two short predicates:
merge0(A, B, Prev, Next) :- append(Prev, [[A|B]], Next).
merge(A, B, Result) :- foldl(merge0, A, B, [], Result).
Here is example of input and output:
a(X) :- X = [a,b,c,d].
b(X) :- X = [[1,2,3,4],[5,6,7,8],[43,34,56,5],[23,32,2,2]].
?- a(A), b(B), merge(A, B, Result).
Result = [[a, 1, 2, 3, 4], [b, 5, 6, 7, 8], [c, 43, 34, 56, 5], [d, 23, 32, 2, 2]].
try this:
delete(X, [X|T], T).
delete(X, [Y|T], [Y|L]):-
delete(X, T, L).
insert(X, List, BigList):-
delete(X, BigList, List).
if([],X,X).
if([H1|T1],[H2|T2],[SH|ST]):-
insert(H1,H2,SH),!,
if(T1,T2,ST).
I doubled checked, it works.
"if" stands for "insert first".