mt([],[],[]).
mt([X|Xs],[Y|Ys],[Z|Zs]) :-
    m(X,Y,Z),
    mt(Xs,Ys,Zs).

m(0,_,0).
m(1,X,Y) :- m1(X,Y).
m(2,X,Y) :- m2(X,Y).

m1(0,0).
m1(1,0).
m1(2,1).

m2(0,0).
m2(1,2).
m2(2,2).

g1([0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2]).
g2([0,0,0,1,1,1,2,2,2,0,0,0,1,1,1,2,2,2,0,0,0,1,1,1,2,2,2]).
g3([0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2]).

:- use_module(library(ordsets),[
				ord_union/3,
				ord_subtract/3
]).

solution(Solution) :-
    g1(G1),
    g2(G2),
    g3(G3),
    solution([],[G1,G2,G3],Solution).

solution(State,New,Solution) :-
    ord_union(New,State,State1),
    ord_subtract(New,State,New1),  % New1 is the _really_ new stuff.
    solution(New1,State,State1,Solution).

solution([],State,_,State). % When there is nothing new, we know that State = Solution.
solution([New|News],Old,State,Solution):-  % Having new stuff in [H|T] form ensures that an empty list can't satisfy this clause.
    products(Old,[New|News],Prods), 
    solution(State,Prods,Solution).

products(Old,New,Prods) :-
    products(Old,New,Prods0,Prods1),
    products(New,Old,Prods1,Prods2),
    products(New,New,Prods2,[]),
    sort(Prods0,Prods).

products([],_,P,P).
products([X|Xs],Ys,P0,P) :-
    products1(Ys,X,P0,P1),
    products(Xs,Ys,P1,P).

products1([],_,P,P).
products1([Y|Ys],X,[Z|P0],P) :-
    mt(X,Y,Z),
    products1(Ys,X,P0,P).


    
			      
