我正在尝试使用返回元素的函数在列表中重复n次。像这样:
repeat([a,a,c,a,b,b,b,b,a,g],4,E).
结果应为E = b
。最简单的方法是什么?这4个元素也必须是连续的。
获取所有元素出现的代码计数:
precondition(Clause):-
Clause =.. [_|ARGS],
( maplist(var,ARGS) -> true; Clause ).
count( [], [] ).
count( [X], [(X,1)] ) :- !.
count( [H|Q], [(H,1),(HR,NR)|QR] ) :-
count( Q, [(HR,NR)|QR] ),
H \= HR,
!.
count( [H|Q], [(H,NR)|QR] ) :-
precondition( succ(N,NR) ),
count( Q, [(H,N)|QR] ),
succ(N,NR).
答案 0 :(得分:3)
如果您拥有类似的列表,则可以使用member/2
:
?- R = [(a, 2), (c, 1), (a, 1), (b, 4), (a, 1), (g, 1)],
member((Element, 4), R).
R = [(a, 2), (c, 1), (a, 1), (b, 4), (a, 1), (g, 1)],
Element = b ;
false.
如果您制作了像[a-2, c-1, a-1, ...]
这样的列表,那么它会更像Prolog一样,然后使用member(Element-4, R)
代替。像(a, b, ...)
这样的术语不像其他语言一样的元组,a-b
通常用作一对。
如果我使用SWI-Prolog提供的库,我将如何做到这一点:
L = [a,a,c,a,b,b,b,b,a,g], N = 4,
pairs_keys_values(Ps, L, L),
group_pairs_by_key(Ps, G),
include([X-Xs]>>length(Xs, N), G, R),
member(Element-_, R).
% some results you don't need
Element = b.
include
行不是严格必要的,但它避免了不必要的选择点。
答案 1 :(得分:2)
可能还需要做一些测试,但这是我的解决方案(比较运算符是整数):
repeat([L], 0, X) :- L \= X.
repeat([L], 1, X) :- L == X.
repeat([X|T], C, X) :- C1 is C - 1, repeat(T, C1, X).
repeat([_|T], C, X) :- repeat(T, C, X).
编辑我注意到为您的示例提供的解决方案也将返回E=a
,但它不应该。所以这是新方法:从给定生成所有子列表,检查生成的列表是否包含相同的元素,然后检查这些列表的长度是否是第二个参数C
sublist([],[]).
sublist([H|T], [H|Q]) :- sublist(T,Q).
sublist([_|T], Q) :- sublist(T,Q).
sameelements([X], X).
sameelements([X|T], X) :- sameelements(T, X).
len([], 0).
len([_|T], C) :- len(T, C1), C is C1 + 1.
repeat(L, C, X) :- sublist(L, SL), len(SL, C), sameelements(SL, X).