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

时间:2013-12-04 20:33:06

标签: 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 + ...,
    Price is Burger*5 + Fries*2 + ...,
    C =< Calories.

其中'...'表示食品清单前一个到结尾的延续。基本上,您可以购买每件商品中的一件,并使用01来表明(这是规格的所有部分)。

我需要找到低于或等于一定卡路里量的最昂贵的食物组合。我被允许创建多个规则来执行此操作。它应该是这样的:

|?- most_expensive(1000, Price, Burger, Fries, Shake, Salad)

它将返回1000卡路里最昂贵的食物组合。我知道我需要进行某种递归比较,但我不确定如何继续。为了记录,我很了解递归,只是不是Prolog。任何人都可以解释一下我是如何实现这一目标的吗?

1 个答案:

答案 0 :(得分:1)

所以,你省略了一些代码,但我收集的是你拥有的代码:

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.

如果劳动密集型,这似乎是明智的。现在,您可以轻松列举@ mbratch建议之后的所有可能性:

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).

这声明最昂贵的选项是没有其他选项以更高的价格满足最大卡路里约束的选项。尝试它似乎成功了:

?- most_expensive_under(1000, Calories, Price, Burgers, Fries, Shakes, Salads).
Calories = 850,
Price = 14,
Burgers = Fries, Fries = Salads, Salads = 1,
Shakes = 0 ;
false.

请记住,这种解决方案是O(N ^ 2)。我提出它只是为了说明统一的力量 - 这不是一个好主意,性能明智。一个更好的想法是使用setof/3,对其结果进行排序,如@mbratch建议的那样,或library(aggregate),我从未使用过,但听到了很好的事情。