Prolog 求和与比较的规则失败

Prolog 求和与比较的规则失败,prolog,Prolog,我的问题是关于在Prolog中表示列表的问题。 我有两个知识库,我需要展示他们可以购买的产品和价格,而不是所有的产品。条件是每个人都可以花钱 %. The knowledge base of elements and their prices. product (cookies, 3). product (coca_cola, 2). product (potatoes, 2). product (tomatoes, 4). product (meat, 6). product (fish,

我的问题是关于在Prolog中表示列表的问题。
我有两个知识库,我需要展示他们可以购买的产品和价格,而不是所有的产品。条件是每个人都可以花钱

%. The knowledge base of elements and their prices.

product (cookies, 3).
product (coca_cola, 2).
product (potatoes, 2).
product (tomatoes, 4).
product (meat, 6).
product (fish, 4).

%. The knowledge base of people and their spending money.

person (aria, 10).
person (Robert, 16).
person (Jim, 20).

% The rule I need to show name's person and the products and it's price, that each person 
% can buy with the money they have.
% Once I get this, I need her to propose me products at random, 
% until I reach the money of each person.


show_products(X,Y):-product(X,Y).
show_persons(X,Y):-person(X,Y).

% With this I show all persons with all products price.
show_product_spend(X,Y,Z):-person(X,_),product(Y,Z).

% Apend is not sufficiently instantiated in that rule...
show_product_2(X,Y,Z):-person(X,Money), product(Y,Z), Apend is Z + Apend, Apend < Money.

% But if it is instantiated. Add is Z+Add, it do not add, compare.
% and Add < Money return false.
instantiate(0).
show_product_3(X,Y,Z):-person(X,Money), product(Y,Z), instantiate(Add), Add is Z + Add, Add < Money.
但这对我不起作用,这显示了一系列的结果

我希望有人能帮助我。
谢谢

欢迎来到SO。请注意,变量以大写字母开头,因此事实

person (Robert, 16).
person (Jim, 20).
不要陈述任何有关罗伯特或吉姆的信息,但以下信息将:

person(robert, 16).
person(jim, 20).
此外,我的SWI prolog不允许谓词名称和括号之间存在空格

你真的应该学习列表,因为它们会解决你的问题。当您看到这些括号时,您就知道它是一个列表:
[…]
。使用列表时,通常将其分为第一个元素
H
(head元素)和另一个元素
T
(tail),编写为
[H | T]
,例如:

?- L=[a,b,c], L=[H|C].
L = [a, b, c],
H = a,
C = [b, c].

好的,如果我理解正确的话,你想为每个人提供他或她能买到的所有食物。这看起来像这样:

spend_money_on_products(P,L)
其中,
p
是一个人,而
L
是一份该人能负担得起的食物及其价格的清单。
我将把我的代码放在这里,一步一步地解释它

getproducts(M,In,[(Prod,Amount)|Out]):-
    product(Prod,Amount), % guess product
    \+ member(Prod,In), % no duplicates
    Amount =< M, % enough money
    Mnew is M - Amount, % subtract
    getproducts(Mnew,[Prod|In],Out).
getproducts(_, _, []).

spend_money_on_products(P,L):-
    person(P,M),
    getproducts(M,[],L).
现在我们需要定义如何处理
getproducts/3
。这个谓词有3个参数:Money left、一个表示购物篮的列表和一个表示装满了价格的购物篮的列表。首先,我们猜测一种产品
Prod
,其价格
金额
产品(Prod,Amount)
)。然后,我们检查此项目是否尚未在购物篮中(
\+成员(Prod,in)
\+/2
可以被视为未在购物篮中)。如果您对列表中的重复项不感兴趣,可以删除此行

下一步是检查是否有足够的钱用于此项目(
Amount=
)。如果是这样,您可以减去该金额(
Mnew是M-金额
)。现在你有了一笔不同的钱(
Mnew
),你应该把一个产品作为列表的头元素添加到你的购物篮中(
[Prod|In]
)。现在你可以用新的金额和新的篮子再次问这个问题
getproducts(Mnew[Prod | In],Out)

一旦找不到剩下的项目,您将返回一个空列表(
getproducts(,,[])。
)。操作的顺序由它们的位置决定,因此它首先尝试根据第一条规则匹配每个产品,如果没有找到任何产品,它只会说退货篮为空

我们忘了一件事:回程篮还没有装满。这是通过在匹配(第一行)时“收集”所有购买的物品来完成的:
getproducts(M,In,[(Prod,Amount)| Out])
。一旦您成功地找到了价格
金额
的项目
Prod
,您就可以将其作为购物篮中的头元素

让我们测试一下:

?- spend_money_on_products(aria,L).
L = [(cookies,3), (coca_cola,2), (potatoes,2)] ;
L = [(cookies,3), (coca_cola,2), (tomatoes,4)] ;
L = [(cookies,3), (coca_cola,2), (fish,4)] ;
L = [(cookies,3), (coca_cola,2)] ;
L = [(cookies,3), (potatoes,2), (coca_cola,2)] ;
...

看起来不错。请注意,每一行都是不同的购物篮。它们之间用分号分隔
。空篮子也可以。

你帮了大忙。我非常感激。我不认为我可以这样利用列表。我只需要你给我一行,而不是几个组合。通过研究,我发现使用:
code
一次(在产品上花钱(aria,L))<代码>代码
它会有所帮助。也用“!”来剪切,但我必须回顾一下如何使用它。非常感谢你。问候您。@plasben20首先尝试熟悉列表和递归。切割有点混乱,所以在使用之前一定要了解基本知识。好的,我会的。非常感谢你所做的一切!
getproducts(M,[],L)
?- spend_money_on_products(aria,L).
L = [(cookies,3), (coca_cola,2), (potatoes,2)] ;
L = [(cookies,3), (coca_cola,2), (tomatoes,4)] ;
L = [(cookies,3), (coca_cola,2), (fish,4)] ;
L = [(cookies,3), (coca_cola,2)] ;
L = [(cookies,3), (potatoes,2), (coca_cola,2)] ;
...