基于另一个基于Prolog上另一个列表的列表编写列表

时间:2016-08-07 21:16:49

标签: prolog

好的,这让我大吃一惊。

% Ok, that's how we find the occurrences of given element in list
% occurrences([a,b,c,a],a,X).
% -> X = 2.

occurrences([],_,0).
occurrences([X|Y],X,N):- occurrences(Y,X,W),N is W + 1.
occurrences([X|Y],Z,N):- occurrences(Y,Z,N),X\=Z.

但是,如果我们使用两个列表呢?让我解释。 在这里,我们有Id,名称,口味和价格的水果。

%fruit(FId, N, T, M (M is for Money as P is for person)).
fruit(1, 'apple'            , sweet  , 5).
fruit(2, 'greenApple'       , bitter , 5).
fruit(3, 'grape'            , sweet  , 10).
fruit(4, 'peach'            , sweet  , 20).
fruit(5, 'orange'           , citric , 5).
fruit(6, 'tangerine'        , citric , 7).
fruit(7, 'banana'           , sweet  , 3).
fruit(8, 'lemon'            , citric , 6).
fruit(9, 'bitterMelons', citric , 12).
fruit(10,'grapefruit'       , citric , 8).

%person(PId, P).
person(1, 'ana').
person(2, 'john').

%ate(PId, FId).
ate(1, [1, 2, 3, 4]).
ate(2, [1, 3, 5, 8]).

person_ate(P, F, T, M) :-
person(PId, P),
ate(PId, FruitIds),
member(FId, FruitIds),
fruit(FId, F, T, M).

另外,我有这些规则来定义水果是否昂贵。

cheap_fruit(FId, F, T, M)                   :- fruit(FId, F, T, M), M =< 6.
expensive_fruit(FId, F, T, M)               :- fruit(FId, F, T, M), M > 15.
middleprice_fruit(FId, F, T, M)             :- fruit(FId, F, T, M), M > 6, M =< 12.

所以,查询

person_ate('ana', F, _, _). or person_ate('ana', _, T, _).

我知道什么是水果,它们是什么类型的水果。但我怎么算数?

这是我尝试过的。

%occurrences(list, item in given list ,number of items).

occurrences(person_ate(_, _, _, _),_,0).

occurrences(person_ate(P, F, T, _),T,N):- 
            occurrences(person_ate(P, F, T, _),T,W),
            N is W + 1.
occurrences(person_ate(P, F, T, _, _),Z,N):- 
            occurrences(person_ate(P, F, T, _, _),Z,N),
            T\=Z.

现在,理论上,如果我查询

occurrences(person_ate('ana', _, T, _),T,N).

我会得到她吃了多少甜,苦,柠檬水果,而我只是得到了

N = 0.
N = 1.
N = 2.
N = 3.
N = 4.
N = 5.
....

永远如此(我的意思是我可以永远执行这个,N永远不会停止提升,而这不是我想要的)。如果我查询

occurrences(person_ate('ana', _, sweet, _),T,N).

occurrences(person_ate('ana', _, T, _),sweet,N).

它只是返回

N = 0
N = 1,
T = sweet
N = 2,
T = sweet
N = 3,
T = sweet
N = 4,
T = sweet
N = 5,
T = sweet
....

等永远...这必须工作,以便我推荐水果。我想根据人们吃的水果类型推荐水果,或者根据“价格规则”(确定水果价格是否昂贵的水平)来推荐水果,为此,我要计算多少甜,苦和柠檬酸水果这个人吃了。

recommending_fruits :- 
    write('Choose someone '), 
    read(Person), 
    pessoa(X, Person), 
    ate(X, FruitIds),
    fruit(Y, _, T, _, _), filme(Y,N,T,_,_), write(N).

1 个答案:

答案 0 :(得分:1)

  

我知道什么是水果,它们是什么类型的水果。但是怎么样   我可以数数吗?

您可以使用findall/3

在这种情况下,我想您可以定义一个简单的元素列表计数器(第一个occurrences/3的简化版本)

listLen([], 0).

listLen([_ | L], N1) :-
  listLen(L, N0), N1 is N0+1.

并将其与findall/3

相结合
findall(F, person_ate('ana', F, _, _), L),
listLen(L, N),
write(N), nl,

你可以在N中获得ana的果实数量。

您的occurrences/3无效(如果我没错),因为

occurrences(person_ate(P, F, T, _),T,N):- 
            occurrences(person_ate(P, F, T, _),T,W),
            N is W + 1.

您使用相同的occurrences和相同的person_ate递归调用T,递增N。所以occurrences递归永远不会结束。

p.s:抱歉我的英语不好。