我正在尝试编写一个谓词
fourExactly(X, List)
,它检查变量X
是否在List
中出现了四次。如果是这种情况,谓词应该为 true,如果不是,则谓词应该为 false。这是我当前的实现:
fourExactly(X, List) :-
count_occurrences(X, List, 4).
% Base case: An empty list has zero occurrences of any element.
count_occurrences(_, [], 0).
% Recursive case: If the head of the list is X, increment the count.
count_occurrences(H, [H|T], Count) :-
count_occurrences(H, T, RestCount),
Count is RestCount + 1.
% Recursive case: If the head of the list is not X, do not increment the count.
count_occurrences(H, [_|T], Count) :-
count_occurrences(H, T, Count).
如果
X
中的 List
少于四个(假),并且恰好有四个(真),我当前的实现可以正常工作。如果超过四个,它将停止正常运行,输出如下所示:
?- fourExactly(n, [n, n, n, n, n, a]).
Yes (0.00s cpu, solution 1, maybe more)
Yes (0.00s cpu, solution 2, maybe more)
Yes (0.00s cpu, solution 3, maybe more)
Yes (0.00s cpu, solution 4, maybe more)
Yes (0.00s cpu, solution 5, maybe more)
No (0.00s cpu)
我认为这与 Prolog 的后链有关,但我不知道如何解决它。我将不胜感激任何帮助。
提前感谢您的帮助
使用
dif
,从零开始计数,并防止计数超过最大值(如果指定了最大值):
select_eq_count(L, E, C) :-
% Start counting at 0
select_eq_count_(L, E, 0, C).
% End of list, so unify the count
select_eq_count_([], _, C, C).
select_eq_count_([H|T], E, U, C) :-
% Different
dif(H, E),
select_eq_count_(T, E, U, C).
select_eq_count_([E|T], E, U, C) :-
% The head of the list is equal to the element
% Prevent exceeding the count if specified
( nonvar(C)
% Comparing Count to Upto
-> C > U
; true
),
U1 is U + 1,
select_eq_count_(T, E, U1, C).
这是非常普遍的,例如无需指定计数:
?- length(L, 2), select_eq_count(L, E, C).
L = [_A, _B],
C = 0,
dif(_A, E),
dif(_B, E) ;
L = [_A, E],
C = 1,
dif(_A, E) ;
L = [E, _A],
C = 1,
dif(_A, E) ;
L = [E, E],
C = 2.
...然后可以数到 4,例如:
?- length(L, 5), select_eq_count(L, E, 4).
L = [_A, E, E, E, E],
dif(_A, E) ;
L = [E, _A, E, E, E],
dif(_A, E) ;
L = [E, E, _A, E, E],
dif(_A, E) ;
L = [E, E, E, _A, E],
dif(_A, E) ;
L = [E, E, E, E, _A],
dif(_A, E) ;
false.