所以我正在制作一个倒计时游戏,我想检查一个列表是否包含另一个列表的元素。
给出两个列表,检查第二个列表是否涵盖第一个列表,即检查第一个列表中出现K次的每个项目是否也在第二个列表中出现至少K次:
实施例
cover([a,e,i,o], [m,o,n,k,e,y,b,r,a,i,n]).
Yes
cover([e,e,l], [h,e,l,l,o]).
no
我跟着一篇文章给了我大量的练习例子,到目前为止我做得还不错,但这个让我有些停滞不前。
我写过这个,
cover([],_).
cover([Head|Tail], List2):-
member(Head, List2),
cover(Tail, List2).
问题是,它没有考虑列表中的K次,
我一直在挠头几个小时, 任何指针都会很棒。
答案 0 :(得分:2)
您非常接近解决方案!
要完全解决它,请考虑member/2
的轻微泛化:在这种情况下我们将使用的构建块与member/2
非常相似,但具有以下扭曲:我们让第三个参数表示剩余列表是什么,我的意思是列表没有“成员”。
传统上,这个谓词被称为select/3
,这是一个非常糟糕的名称,因为它表明我们只能在一个方向上使用谓词。这相当命令式。
我将使用更具描述性的声明性名称并将其称为 selection/3
。
想想这样的关系:
selection(E, [E|Ls], Ls). selection(E, [L|Ls], [L|Rest]) :- selection(E, Ls, Rest).
您可以将member/2
视为selection/3
的特例,因为我们可以用member/2
来定义selection/3
,而不是关心剩余的列表:
member(E, Ls) :- selection(E, Ls, _).
使用selection/3
,我们可以写:
list_cover([], _). list_cover([L|Ls], Cs0) :- selection(L, Cs0, Cs), list_cover(Ls, Cs).
我们可以阅读第二条如下:
如果
L
是Cs0
的成员,则Cs
是剩余列表(即Cs0
没有L
),和Cs
涵盖Ls
,然后Cs0
涵盖[L|Ls]
。
请注意命名约定,理想情况下会明确每个参数的含义。在我们的例子中,第二个参数是覆盖列表。简单地称呼cover/2
并不能说明哪个论点实际上代表了封面。
示例查询和答案:
?- list_cover([a,e,i,o], [m,o,n,k,e,y,b,r,a,i,n]). true . ?- list_cover([a,a,a], [a,a]). false. ?- list_cover([a,a,a], [a,a,b,a]). true .
进一步说:
?- list_cover(Ls, Cs). Ls = [] ; Ls = [_1900], Cs = [_1900|_1908] ; Ls = [_1900, _1912], Cs = [_1900, _1912|_1920] .
很酷,不是吗?这很普遍!