Recursion 如何在Prolog中找到与参数匹配的特定条件?

Recursion 如何在Prolog中找到与参数匹配的特定条件?,recursion,prolog,Recursion,Prolog,我不熟悉Prolog,很困惑。我们正在讨论递归和成员。我的任务是根据快餐的种类、热量和价格,找到不同的组合: burger 450 $5 fries 250 $2 shake 500 $3 salad 150 $7 我创建了一个规则: findfood(Calories, Price, Burger, Fries, Shake, Salad) :- member(Burger, [0,1]), ..., C is Burger*450 + Fries*250 +

我不熟悉Prolog,很困惑。我们正在讨论递归和成员。我的任务是根据快餐的种类、热量和价格,找到不同的组合:

burger 450 $5 
fries 250 $2 
shake 500 $3 
salad 150 $7
我创建了一个规则:

findfood(Calories, Price, Burger, Fries, Shake, Salad) :-
    member(Burger, [0,1]),
    ...,
    C is Burger*450 + Fries*250 + ...,
    Price is Burger*5 + Fries*2 + ...,
    C =< Calories.

它将以1000卡路里的热量返回最昂贵的食物组合。我知道我需要做一些递归比较,但我不确定如何继续。作为记录,我非常理解递归,只是不懂Prolog。有人能解释一下我是如何做到这一点的吗?

因此,您省略了一些代码,但我想这就是您所拥有的:

findfood(Calories, Price, Burger, Fries, Shake, Salad) :-
    member(Burger, [0,1]),
    member(Fries, [0,1]),
    member(Shake, [0,1]),
    member(Salad, [0,1]),
    Calories is Burger * 450 + Fries * 250 + Shake * 500 + Salad * 150,
    Price is Burger * 5 + Fries * 2 + Shake * 3 + Salad * 7.
这似乎是明智的,即使是劳动密集型的。现在,您可以根据@mbrach的建议轻松列举所有可能性:

all_combos(Combinations) :-
    setof((C,P,B,F,Sh,Sa), findfood(C,P,B,F,Sh,Sa), Combinations).
您还可以滥用Prolog从以下内容中获得所需的解决方案:

most_expensive_under(MaximumCalories, Calories, Price, Burgers, Fries, Shakes, Salads) :-
    all_combos(Combos),
    member((Calories, Price, Burgers, Fries, Shakes, Salads), Combos),
    Calories =< MaximumCalories,
    \+ (member((Calories2, Price2, _, _, _, _), Combos),
        Calories2 =< MaximumCalories,
        Price2 > Price).

请记住,这种解决方案是O(N^2)。我提出它只是为了说明统一的力量,从性能上看,这不是一个好主意。一个更好的方法是使用
setof/3
,它按照@mbrach的建议对结果进行排序,或者使用
library(aggregate)
,我从未使用过它,但听说过它的好处。

您的规则将迭代生成卡路里总量小于或等于卡路里的组合。您可以使用
setof
构建它们的排序列表。因此,你可以从列表的一端选择这篇文章。例如,
setof((P,B,F,Sh,Sa),findfood(1000,P,B,F,Sh,Sa),allfoodOrder),reverse(allfoodOrder,BigFirst),BigFirst=[Biggy |)。
将使
Biggy
成为一组值
(价格、汉堡、薯条、奶昔、沙拉)
代表最高价格。制定此项后,我得到一个简单的输出:否。如果我尝试所有的组合,我也会得到否。我想错误可能在这里。有什么想法吗?你的
findfood/6
和我的一样吗?哦,我没看到你删除了我的最后一行。谢谢
most_expensive_under(MaximumCalories, Calories, Price, Burgers, Fries, Shakes, Salads) :-
    all_combos(Combos),
    member((Calories, Price, Burgers, Fries, Shakes, Salads), Combos),
    Calories =< MaximumCalories,
    \+ (member((Calories2, Price2, _, _, _, _), Combos),
        Calories2 =< MaximumCalories,
        Price2 > Price).
?- most_expensive_under(1000, Calories, Price, Burgers, Fries, Shakes, Salads).
Calories = 850,
Price = 14,
Burgers = Fries, Fries = Salads, Salads = 1,
Shakes = 0 ;
false.