我正在定义一个函数alternate_func(Ps,P),其中Ps是列表列表,P是Ps中所有元素的列表,其行为方式如下:。
?- 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)
这是我到目前为止尝试过的,
alternate_func([[], L], L).
alternate_func([[H|T], []], [H|T]).
alternate_func([[X|L1], [Y|L2]], [X,Y|L3]) :-
alternate_func([L1, L2], L3).
我得到的情况 1 的正确结果,但 2、3 和 4 失败。这里有什么问题?
此解决方案处理将头/尾从每个列表中拆分的列表列表。 之后:
- 如果所有的尾巴都是空的,我们就完成了。
- 否则,再次重复该过程,并带有尾巴。
法典:
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).
首先,坚持良好的关系命名。这里没有func
。列表列表和列表之间存在关系。所以最好叫lists_interleaved(Ess, Es)
。
:- 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)
请参阅seqq//1
的定义。
这仍然不是最好的定义。毕竟,?- lists_interleaves(Ess, "abcd").
不会终止。让我们使用失败切片来了解原因:
lists_interleaved(Ess, Es) :- 转置(Ess, EssT),false,phrase(seqq(EssT), Es)。?- lists_interleaved(Ess,"abcd"),假的。 循环。
解决此问题的一种简单方法是在Ess
和Es
之间建立关系。 毕竟,Ess
中的第一个列表最多可以和Es
一样长,而且Ess
不能更长。
通过添加这些限制作为额外目标,我们得到:
lists_interleaved(Ess, Es) :-Ess = [fs|_],Fs = [_|_],list_longer(Ess, Es),list_longer(Fs, Es),转置(Ess, EssT), phrase(seqq(EssT), Es). list_longer([], _). list_longer([_|Es], [_|Fs]) :- list_longer(西班牙,女)。
现在,这将我们限制在至少具有一个元素的Es
。
?- lists_interleaved(Ess, "abcdef").
Ess = ["abcdef"]
; Ess = ["ace","bdf"]
; Ess = ["ad","be","cf"]
; Ess = ["a","b","c","d","e","f"]
; false.
请参阅此答案如何使用紧凑的双引号表示法打印解决方案。
尽管如此,这并不完美,因为这些list_longer/2
目标现在基本上是猜测。但我会保持原样,因为这是你要求的。
(我将悬赏以获得更好的定义/或理由
,为什么这是不可能的)