Search code examples
recursionprolog

Creating a list of interleaved elements: Prolog


I am defining a function alternate_func(Ps, P) where Ps is a list of lists and P is a list of all elements in Ps that behaves in the following way: .

?- alternate_func([[p,q],[r,s]],P). 
P=[p,r,q,s]. (case 1)

?- alternate_func([P,Q,R],[p,q,r,s,t,u]). 
P=[p,s], Q=[q,t], R=[r,u]. (case 2)

?- alternate_func([Q],[1,2,3]). 
Q=[1,2,3]. (case 3)

?- alternate_func([[4,5,6],[3,1],[4,1,2]],X).
false. (because Length of sublists must be same) (case 4)

This is what I have tried so far,

alternate_func([[], L], L).          
alternate_func([[H|T], []], [H|T]).  

alternate_func([[X|L1], [Y|L2]], [X,Y|L3]) :-
    alternate_func([L1, L2], L3).

I am getting correct result for the case 1 but fails for the 2,3 and 4. What is the problem here?


Solution

  • This solution processes the list of lists splitting the head / tail off each list. Afterwards:

    • If all tails are empty we are done.
    • Otherwise the process is repeated again, with the tails.

    Code:

    lists_interleaved( Ess, Es):-
      lists_interleaved( Ess, X-X, Es).
    
    lists_interleaved( [], Head-[], []):-
      maplist(=([]), Head).
    lists_interleaved( [], [First|Head]-[], Es):-
      lists_interleaved( [First|Head], X-X, Es).
    lists_interleaved( [[E|ETail]|Ess], Head-[ETail|Rest], [E|Es]):-
      lists_interleaved( Ess, Head-Rest, Es).