我如何比较序言中的两个列表,如果第二个列表由第一个列表的所有其他元素组成,则返回 true?

How can I compare two lists in prolog, returning true if the second list is made of every other element of list one?

我会通过比较第一个列表的第一个索引并将索引加 2 来解决它。但我不知道如何检查序言中的索引。 另外,我会创建一个计数器,当计数器为奇数时(如果我们从 0 开始计数),它会忽略列表中的内容。 你能帮助我吗? 例子: everyOther([1,2,3,4,5],[1,3,5]) 是真的,但是 everyOther([1,2,3,4,5],[1,2,3]) 不是.

有两种基本情况和一种递归情况:

  1. 您不能从空列表中获取任何奇数元素。
  2. 从长度为 1 的列表中,它包含的唯一元素是一个奇数元素。
  3. 对于长度>2 的列表,我们取第一个元素而不是第二个;列表的其余部分以递归方式处理。

代码如下所示:

odd_ones([], []).
odd_ones([X], [X]):- !.
odd_ones([X,_|T1], [X|T2]):-
  odd_ones(T1, T2).

请注意,在 Prolog 中我们不需要维护必须递增的显式索引等。我们只需使用匹配:[] 匹配空列表,[X] 匹配单例列表, [X,_|T] 匹配长度 >2 的列表。 | 将列表中的前两个元素与列表的其余部分分开(称为列表的 "tail")。 _表示未命名变量;我们甚至对元素不感兴趣。 另请注意删除 (!),它删除了第二个基本案例的空闲选择点。

使用示例:

?- odd_ones([], X).
X = [].
?- odd_ones([a], X).
X = [a].
?- odd_ones([a,b], X).
X = [a].
?- odd_ones([a,b,c], X).
X = [a, c].
?- odd_ones([a,b,c,d], X).
X = [a, c].
?- odd_ones([a,b,c,d,e], X).
X = [a, c, e].

我们提供了三个逻辑上纯的定义,即使您只需要一个 — variatio delectat:)

  1. 两个相互递归的谓词list_oddies/2skipHead_oddies/2:

    list_oddies([],[]).
    list_oddies([X|Xs],[X|Ys]) :-
       skipHead_oddies(Xs,Ys).
    
    skipHead_oddies([],[]).
    skipHead_oddies([_|Xs],Ys) :-
       list_oddies(Xs,Ys).
    
  2. 递归list_oddies/2和非递归list_headless/2

    list_oddies([],[]).
    list_oddies([X|Xs0],[X|Ys]) :-
       list_headless(Xs0,Xs),
       list_oddies(Xs,Ys).
    
    list_headless([],[]).
    list_headless([_|Xs],Xs).
    
  3. A "one-liner" 使用 foldl/4 in combination with Prolog lambdas:

    :- use_module(library(lambda)).
    
    list_oddies(As,Bs) :-
       foldl(\X^(I-L)^(J-R)^(J is -I,( J < 0 -> L = [X|R] ; L = R )),As,1-Bs,_-[]).
    

这三种实现都避免了创建无用的选择点,但它们的做法不同:

  • #1 和#2 使用第一个参数索引。
  • #3 以逻辑上安全的方式使用 (->)/2(;)/2——使用 (<)/2 作为条件。

让我们看看@WouterBeek 给出的查询 !

?- list_oddies([],[]),
   list_oddies([a],[a]),
   list_oddies([a,b],[a]),
   list_oddies([a,b,c],[a,c]),
   list_oddies([a,b,c,d],[a,c]),
   list_oddies([a,b,c,d,e],[a,c,e]),
   list_oddies([a,b,c,d,e,f],[a,c,e]),
   list_oddies([a,b,c,d,e,f,g],[a,c,e,g]),
   list_oddies([a,b,c,d,e,f,g,h],[a,c,e,g]).
true.                                           % all succeed deterministically

感谢 ,我们得到了合乎逻辑的答案——即使是最一般的查询:

?- list_oddies(Xs,Ys).
  Xs = [],                        Ys = []
; Xs = [_A],                      Ys = [_A]
; Xs = [_A,_B],                   Ys = [_A]
; Xs = [_A,_B,_C],                Ys = [_A,_C]
; Xs = [_A,_B,_C,_D],             Ys = [_A,_C]
; Xs = [_A,_B,_C,_D,_E],          Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F],       Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F,_G],    Ys = [_A,_C,_E,_G]
; Xs = [_A,_B,_C,_D,_E,_F,_G,_H], Ys = [_A,_C,_E,_G]
...