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, 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.
我已经搜索了几天,但没有找到解决方案。我很绝望。
我了解到列表有点帮助,但是列表的问题是相似的。
用变量控制产品的累计价格不超过每个人的钱的限制,从而不会继续展示更多的产品。
Prolog 变量不能修改它的数据,这就是问题所在。在我的问题中找到了这个可能的解决方案:
allowed_input (1). % your
allowed_input (2). % knowledge
allowed_input (3). % base
restricted_sum (A, B, C): -
allowed_input (A),% test user input's
allowed_input (B),% validity
C is A + B. % test the result
但这对我不起作用,这显示了结果的组合。
我希望有人能帮助我。谢谢!
解决方案
欢迎来到 SO。请注意,变量以大写字母开头,所以事实
person (Robert, 16).
person (Jim, 20).
不要陈述任何关于名为 Robert 或 Jim 的人的信息,但以下内容会:
person(robert, 16).
person(jim, 20).
此外,我的 SWI 序言不允许谓词名称和括号之间有空格。
你真的应该了解列表,因为这些会解决你的问题。当您看到这些括号时,您就知道这是一个列表:[...]
. 列表通常通过将其分成第一个元素H
(头元素)和一个其余列表T
(尾)来使用,写为[H|T]
,例如:
?- L=[a,b,c], L=[H|C].
L = [a, b, c],
H = a,
C = [b, c].
好吧,如果我理解正确的话,你希望每个人都能买到他或她能买到的所有食物。这看起来像这样:
spend_money_on_products(P,L)
whereP
是一个人,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).
M
所以首先我们需要知道一个人有多少钱P
:person(P,M)
. 简单的。现在我们对这个人P
不再感兴趣,可以专注于金钱M
。现在我们可以从一个空篮子(空 List )开始询问L
我们可以购买的物品:M
[]
getproducts(M,[],L)
现在我们需要定义如何处理getproducts/3
. 这个谓词有 3 个参数:剩下的钱,一个代表购物篮的列表和一个代表已装满价格的购物篮的列表。首先,我们猜测Prod
价格为Amount
( product(Prod,Amount)
) 的产品。然后我们检查这个项目是否已经在篮子里(\+ member(Prod,In)
,\+/2
可以读作没有)。如果您对列表中的重复项不感兴趣,可以删除此行。
接下来是检查是否有足够的钱购买该物品(Amount =< M
)。如果是这样,您可以减去此金额 ( Mnew is M - Amount
)。现在您有不同数量的钱 ( Mnew
),您应该将产品添加到您的购物篮中,将其作为列表 ( [Prod|In]
) 的头部元素。现在你可以用新的金额和新的篮子再次问这个问题getproducts(Mnew,[Prod|In],Out)
。
一旦没有可找到的项目,您将返回一个空列表 ( getproducts(_, _, []).
)。动作的顺序由它们的位置决定,所以它首先尝试按照第一条规则匹配每个产品,如果没有找到任何产品,它只会说退货篮是空的。
我们忘记了一件事:退货篮还没有装满。这是通过在匹配时“收集”所有购买的物品来完成的(第一行)getproducts(M,In,[(Prod,Amount)|Out])
:。一旦你成功找到了一个Prod
价格的项目Amount
,你把它作为你的购物篮中的头元素。
让我们测试一下:
?- 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)] ;
...
看起来挺好的。请注意,每一行都是不同的购物篮。它们用分号隔开;
。空篮子也可以。
推荐阅读
- android - Flutter 错误:“Null”类型不是“String”类型的子类型
- javascript - 在反应钩子中,如何延迟 onInput 事件直到我完成输入
- html - 如何从 Github Repo 在 React 中实现 Raw 图像
- node.js - 如何在nodejs中从出生日期获取年龄
- python - 如何解决 Jupyter Notebook 中的内核错误?
- javascript - soffice 未找到,即使安装了 libreoffice buildpack - heroku 服务器
- python - 如何找到轮廓的中线
- bitnami - 为什么 [bitnami/minio] persistence.mountPath 不被尊重?
- python - 如何使用 daframe 中的数据从 python 更新表
- javascript - 如何在 NuxtAuth v.4 中获取令牌值?