创建交错元素列表:Prolog

时间:2019-04-22 13:33:07

标签: recursion prolog

我正在定义一个函数alter_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,我却没有通过。

2 个答案:

答案 0 :(得分:5)

此解决方案处理列表列表,将头/尾分开。 然后:

  • 如果所有的尾巴都是空的,我们就完成了。
  • 否则,该过程将再次重复进行,带有尾巴。

代码:

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).

答案 1 :(得分:3)

首先,坚持良好的关系命名。这里没有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) :-
   transpose(Ess, EssT), false,
   phrase(seqq(EssT), Es). 

?- lists_interleaved(Ess, "abcd"), false.
** LOOPS **

解决此问题的简单方法是在EssEs之间建立关系。 毕竟,Ess中的第一个列表最多可以与Es一样长,并且Ess也不能更长。

通过将这些限制添加为额外目标,我们得到:

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).

这现在将我们限制为至少包含一个元素的Es

?- lists_interleaved(Ess, "abcdef").
Ess = ["abcdef"] ;
Ess = ["ace","bdf"] ;
Ess = ["ad","be","cf"] ;
Ess = ["a","b","c","d","e","f"] ;
false.

请参见this answer,如何使用紧凑的双引号表示法打印解决方案。

但是,这仍然不是完美的,因为这些list_longer/2目标现在基本上是猜测。但是我会保持原样,因为这就是您要的。

(我会悬赏以寻求更好的定义/或理由,为什么这不可能)