First, stick to good naming of relations. There is no func
tion here. You have a relation between a list of lists and a list. So a name lists_interleaved(Ess, Es)
is preferable.
:- set_prolog_flag(double_quotes, chars). % to permit that "abc" = [a,b,c]
lists_interleaved(Ess, Es) :-
transpose(Ess, EssT),
phrase(seqq(EssT), Es). % alternatively append(EssT,Es)
See the definition of seqq//1
.
Still this is not the nicest definition. After all, ?- lists_interleaves(Ess, "abcd").
does not terminate. Let's use a failure-slice to see why:
lists_interleaved(Ess, Es) :-
transpose(Ess, EssT), false,
phrase(seqq(EssT), Es).
?- lists_interleaved(Ess, "abcd"), false.
loops.
A simple way to fix this is to establish a relation between Ess
and Es
.
After all, the first list in Ess
can be at most as long as Es
, and also Ess
cannot be longer.
By adding these restrictions as extra goals, we get:
lists_interleaved(Ess, Es) :-
Ess = [Fs|_],
Fs = [_|_],
list_longer(Ess, Es),
list_longer(Fs, Es),
transpose(Ess, EssT),
phrase(seqq(EssT), Es).
list_longer([], _).
list_longer([_|Es], [_|Fs]) :-
list_longer(Es, Fs).
This now constrains us to an Es
with at least one element.
?- lists_interleaved(Ess, "abcdef").
Ess = ["abcdef"]
; Ess = ["ace","bdf"]
; Ess = ["ad","be","cf"]
; Ess = ["a","b","c","d","e","f"]
; false.
See this answer how to print solutions using compact double-quotes notation.
And still, this isn't perfect as these list_longer/2
goals are now essentially guessing. But I will leave it as is since this is what you asked for.
(I will put a bounty for a better definition/or justification why this is not possible)