我如何比较序言中的两个列表,如果第二个列表由第一个列表的所有其他元素组成,则返回 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 的列表,我们取第一个元素而不是第二个;列表的其余部分以递归方式处理。
代码如下所示:
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:)
两个相互递归的谓词list_oddies/2
和skipHead_oddies/2
:
list_oddies([],[]).
list_oddies([X|Xs],[X|Ys]) :-
skipHead_oddies(Xs,Ys).
skipHead_oddies([],[]).
skipHead_oddies([_|Xs],Ys) :-
list_oddies(Xs,Ys).
递归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).
A "one-liner" 使用 meta-predicate 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
感谢 logical-purity,我们得到了合乎逻辑的答案——即使是最一般的查询:
?- 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]
...
我会通过比较第一个列表的第一个索引并将索引加 2 来解决它。但我不知道如何检查序言中的索引。 另外,我会创建一个计数器,当计数器为奇数时(如果我们从 0 开始计数),它会忽略列表中的内容。 你能帮助我吗? 例子: everyOther([1,2,3,4,5],[1,3,5]) 是真的,但是 everyOther([1,2,3,4,5],[1,2,3]) 不是.
有两种基本情况和一种递归情况:
- 您不能从空列表中获取任何奇数元素。
- 从长度为 1 的列表中,它包含的唯一元素是一个奇数元素。
- 对于长度>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:)
两个相互递归的谓词
list_oddies/2
和skipHead_oddies/2
:list_oddies([],[]). list_oddies([X|Xs],[X|Ys]) :- skipHead_oddies(Xs,Ys). skipHead_oddies([],[]). skipHead_oddies([_|Xs],Ys) :- list_oddies(Xs,Ys).
递归
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).
A "one-liner" 使用 meta-predicate
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
感谢 logical-purity,我们得到了合乎逻辑的答案——即使是最一般的查询:
?- 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]
...