如何编写一个以List1和List2作为输入的prolog程序,结果列表是List1和List2的交替元素?

时间:2017-10-07 19:44:39

标签: list recursion prolog artificial-intelligence

这是我第一次尝试使用非样本程序上的列表递归,因为我缺乏经验!

预期的有效查询:

mixElements([],[a,b,c], [a,b,c]).
mixElements([a,b],[],[a,b]).
mixElements([a,b,c],[d,e,f],[a,d,b,e,c,f]).
mixElements([a,b,c],[d,e,f,g,h],[a,d,b,e,c,f,g,h]).

这里我尝试为输入列表为空时创建基本案例,只返回结果。

/* Base cases */
mixElements([],[],Result).

我的递归语句的逻辑是输入列表必须至少有1个或更多元素。因此,对于列表1和2,它们必须分别由[H | L]表示。然后它将H1和H2附加到Result以创建列表元素的交替模式。最后,它将调用mixElements与列表的其余部分L1和L2,以及现在应包含两个列表的第一个头元素的Result列表。

/* Recursive case where both L1 and L2 are not empty */
mixElements([H1|L1],[H2|L2],Result) :- append(H1,H2,Result), mixElements(L1,L2,Result).

我的结果输出总是"没有"。

3 个答案:

答案 0 :(得分:3)

在处理列表时,考虑DCG通常是值得的,因为它们产生易于阅读的代码。它进一步有助于为关系选择描述性名称,比如list_list_interlocked / 3。请考虑以下代码:

list_list_interlocked(L1,L2,I) :-
   phrase(interlocked(L1,L2),I).

interlocked([],[]) -->           % if both input lists are empty
   [].                           % the resulting list is also empty
interlocked([],[H2|T2]) -->      % if the first input list is empty
   [H2],                         % the head of the second is in the list
   interlocked([],T2).           % the relation holds for the tail as well
interlocked([H1|T1],[]) -->      % if the second input list is empty
   [H1],                         % the head of the first is in the list
   interlocked(T1,[]).           % the relation holds for the tail as well
interlocked([H1|T1],[H2|T2]) --> % if both lists are non-empty
   [H1,H2],                      % the heads are in the list
   interlocked(T1,T2).           % the relation holds for the tails as well

您的示例查询会产生所需的结果:

   ?- list_list_interlocked([],[a,b,c],I).
I = [a,b,c]
   ?- list_list_interlocked([a,b],[],I).
I = [a,b]
   ?- list_list_interlocked([a,b,c],[d,e,f],I).
I = [a,d,b,e,c,f]
   ?- list_list_interlocked([a,b,c],[d,e,f,g,h],I).
I = [a,d,b,e,c,f,g,h]

答案 1 :(得分:0)

基本上有四种情况:

  1. 第一个列表为空,第二个列表为空,在这种情况下结果应为空:

    mixElements([],[],[]).
    
  2. 第一个列表为空,第二个列表为非空,在这种情况下,结果是第二个列表:

    mixElements([],[H2|T2],[H2|T2]).
    
  3. 第一个列表非空,第二个列表为空,在这种情况下,结果是第一个列表:

    mixElements([H1|T1],[],[H1|T1]).
    
  4. finall两个列表都是非空的,在这种情况下,结果的两个第一个元素是列表的头部,然后混合列表的尾部:

    mixElements([H1|T1],[H2|T2],[H1,H2|TT]) :-
        mixElements(T1,T2,TT).
    
  5. 现在我们可以把它们放在一起:

    mixElements([],[],[]).
    mixElements([],[H2|T2],[H2|T2]).
    mixElements([H1|T1],[],[H1|T1]).
    mixElements([H1|T1],[H2|T2],[H1,H2|TT]) :-
        mixElements(T1,T2,TT).
    

    现在我们已经创建了一些冗余语句。例如,我们可以将前两个语句合并为一个,例如:

    mixElements([],L,L).
    mixElements([H1|T1],[],[H1|T1]).
    mixElements([H1|T1],[H2|T2],[H1,H2|TT]) :-
        mixElements(T1,T2,TT).
    

    我将其作为练习来进一步改进谓词。例如,您可以使用剪切,但这可以消除谓词的多方向,这有时非常有用。

答案 2 :(得分:0)

你正在使用append / 3,而不需要它。当模式由至少一个元素的2个列表组成时,您可以立即获得结果,然后递归以处理尾部:

mixElements([H1|L1],[H2|L2],[H1,H2|Rest]) :-
    !, mixElements(L1,L2,Rest).
mixElements(L1,L2,Rest) :- append(L1,L2,Rest).