查找列表中最常见的项目,然后返回随机项目

时间:2016-12-06 10:45:43

标签: prolog

我正在寻找列表中最常见的项目,但我得到了很多随机结果。不知道为什么。

这是我的代码:

find_most_common([], []).
find_most_common(List, E) :-
 msort(List, [H|T]),
 find_most_common(T, H, H, 1, 0, E).

find_most_common([], H, _, C1, C2, H) :- 
 C1 >= C2.
find_most_common([], _, X, C1, C2, X) :- 
 C1 < C2. 

find_most_common([H|T], H, L, C1, C2, E) :-
 find_most_common(T, H, L, C1 + 1, C2, E).


find_most_common([X|T], H, L, C1, C2, E) :-
( 
 C1 > C2 ->  find_most_common(T, X, H, 1, C1, E) ; 
 find_most_common(T, X, L, 1, C2, E)
).

这是我得到的结果:

?- find_most_common([a,b,b,a,a], E).
E = a ;
E = a ;
E = b ;
E = a ;
E = b ;
E = a ;
E = b ;
E = b ;
false.

我应该这样做:

?- find_most_common([a,b,b,a,a], E).
E = a ;
false.

3 个答案:

答案 0 :(得分:1)

你需要告诉Prolog停止使用“cut”搜索替代品。

例如,如果您在此子句中添加以下“cut”...

find_most_common([H|T], H, L, C1, C2, E) :- !,
 find_most_common(T, H, L, C1 + 1, C2, E).

它只能为您提供的输入找到一个答案。

在这种情况下应该发生什么?

  

find_most_common([a,a,a,b,b,b],E)。

它应该返回a还是b?它目前将返回b。

提示

如果您使用trace.运行程序,当您要求重做时,您可以看到哪个子句正在“重做”......

(这不加额外的切割)

[trace] 3 ?- find_most_common([a,b,b,a,a], E).
   Call: (6) find_most_common([a, b, b, a, a], _G3171) ? creep
   Call: (7) msort([a, b, b, a, a], [_G3251|_G3252]) ? creep
   Exit: (7) msort([a, b, b, a, a], [a, a, a, b, b]) ? creep
   Call: (7) find_most_common([a, a, b, b], a, a, 1, 0, _G3171) ? creep
   Call: (8) find_most_common([a, b, b], a, a, 1+1, 0, _G3171) ? creep
   Call: (9) find_most_common([b, b], a, a, 1+1+1, 0, _G3171) ? creep
   Call: (10) 1+1+1>0 ? creep
   Exit: (10) 1+1+1>0 ? creep
   Call: (10) find_most_common([b], b, a, 1, 1+1+1, _G3171) ? creep
   Call: (11) find_most_common([], b, a, 1+1, 1+1+1, _G3171) ? creep
   Call: (12) 1+1>=1+1+1 ? creep
   Fail: (12) 1+1>=1+1+1 ? creep
   Redo: (11) find_most_common([], b, a, 1+1, 1+1+1, _G3171) ? creep
   Call: (12) 1+1<1+1+1 ? creep
   Exit: (12) 1+1<1+1+1 ? creep
   Exit: (11) find_most_common([], b, a, 1+1, 1+1+1, a) ? creep
   Exit: (10) find_most_common([b], b, a, 1, 1+1+1, a) ? creep
   Exit: (9) find_most_common([b, b], a, a, 1+1+1, 0, a) ? creep
   Exit: (8) find_most_common([a, b, b], a, a, 1+1, 0, a) ? creep
   Exit: (7) find_most_common([a, a, b, b], a, a, 1, 0, a) ? creep
   Exit: (6) find_most_common([a, b, b, a, a], a) ? creep
E = a ;
   Redo: (10) find_most_common([b], b, a, 1, 1+1+1, _G3171) ? creep
   Call: (11) 1>1+1+1 ? creep
   Fail: (11) 1>1+1+1 ? creep
   Redo: (10) find_most_common([b], b, a, 1, 1+1+1, _G3171) ? creep
   Call: (11) find_most_common([], b, a, 1, 1+1+1, _G3171) ? creep
   Call: (12) 1>=1+1+1 ? creep
   Fail: (12) 1>=1+1+1 ? creep
   Redo: (11) find_most_common([], b, a, 1, 1+1+1, _G3171) ? creep
   Call: (12) 1<1+1+1 ? creep
   Exit: (12) 1<1+1+1 ? creep
   Exit: (11) find_most_common([], b, a, 1, 1+1+1, a) ? creep
...etc...

答案 1 :(得分:1)

这是另一种方法:迭代元素并查找是否更频繁地满足另一个元素(注意比较是针对整数):

my-member([X], X).
my-member([_|T], X) :- my-member(T, X).

count-occur([H], X, 0) :- H =\= X.
count-occur([X], X, 1).
count-occur([H|T], X, C) :- 
    ( H =:= X, count-occur(T, X, C1), C is C1 + 1 ); 
    ( H =\= X, count-occur(T, X, C) ). 

most-common(L, E) :- 
    my-member(L, E),
    count-occur(L, E, C),
    not((my-member(L, Y, C1), Y =\= E, C > C1 )).

答案 2 :(得分:0)

这是我的方法

most_common([], []).
most_common([H|T], M) :-
    nb_occurences([H|T], [], N),
    sort(N, RS),
    reverse(RS, [Max:I|S]),
    member(Max:M, [Max:I|S]).

nb_occurences([], L, L).
nb_occurences([H|T], L, N) :-
    (   select(I:H, L, L2) ->
        J is I + 1
        ;
        J is 1,
        L2 = L
    ),
    nb_occurences(T, [J:H|L2], N).

首先,我们使用nb_occurences/3来构建对Occurences:Element对的列表。然后我们对这些对进行排序并将最后一对出现,以选择我们使用member/2检索的正确输出。