我是prolog的新手,并尝试解决我的问题后面的问题。
我有一些人
person(john, 36).
person(jane, 3).
person(amber, 32).
person(emmy, 2).
person(clement, 37).
person(patrick, 15).
person(emilie, 20).
我有一份代表食物的化合物清单可以是健康的(好的)。
foods([food(frechfries, _), food(apple, good), food(burger,_),
food(kiwi, good), food(banana, good), food(potato, good), food(orange, good),
food(cereal, good), food(hotdog, _), food(steak, _), food(coca, _), food(water, good)]).
我想将每个项目与一个人匹配,向每个人分发一个且仅一个食物。为此,我有以下规则:
distribute(P, F, Results) :- person(P, _), findall(Item, memberchk(Item, F), Results).
不幸的是,每个人都会收到列表中的第一项
如果我尝试使用此规则删除已使用的项目:
distribute(P, F, Results) :- person(P, _), findall(Item, memberchk(Item, F), Results), delete(F, Item, F).
我得到了相同的结果。任何人都能看到我失踪的东西?
答案 0 :(得分:0)
一般来说,听起来你有两个事实集合,你只想为每个唯一匹配对定义一个成功的规则。
事实的集合是person
和food
。正如我在评论中提到的那样,将食物定义为具有列表的单一事实将会有点尴尬。我会像定义food
一样定义person
,也就是说,作为个别事实。
person(john, 36).
person(jane, 3).
person(amber, 32).
person(emmy, 2).
person(clement, 37).
person(patrick, 15).
person(emilie, 20).
food(frechfries, _).
food(apple, good).
food(burger,_).
food(kiwi, good).
food(banana, good).
food(potato, good).
food(orange, good).
food(cereal, good).
food(hotdog, _).
food(steak, _).
food(coca, _).
food(water, good).
现在我们可以考虑定义一场比赛。你可以这样想:
成功的配对包括一个人 - 食物对的列表,其中每个人和每个食物只出现一次(从各自的集合中唯一选择)并且每个人都有代表。
由于我们试图独特地选择每个人和食物,我认为select/3
将是一个很好的选择,作为实现预期目标的核心机制。
person_food_pairs(PeopleFoodPairings) :-
findall(Person, person(Person, _), People),
findall(Food, food(Food, _), Foods),
length(People, NumberOfPeople),
length(Foods, NumberOfFoods),
NumberOfPeople =< NumberOfFoods,
person_food_pairing(People, Foods, PeopleFoodPairings).
person_food_pairing([], _, []).
person_food_pairing(People, Foods, [Person-Food|RemainingPairs]) :-
select(Person, People, RemainingPeople),
select(Food, Foods, RemainingFoods),
person_food_pairing(RemainingPeople, RemainingFoods, RemainingPairs).
会有很多组合,所以有很多解决方案!我没有看到任何其他限制这种情况的条件。此外,您可以省略这一行,由于person_food_pairing/2
的定义,代码仍会产生相同的结果:
length(People, NumberOfPeople),
length(Foods, NumberOfFoods),
NumberOfPeople =< NumberOfFoods,
然而,代码会做很多不必要的执行,最终确定它不能进行配对。所以这些行有助于尽早确定这种情况。
<小时/> 如果,如评论中所述,您的条件涉及某些人和食物属性,则您需要随身携带这些属性,直到您进行配对。
person_food_pairs(PeopleFoodPairings) :-
findall(Person-Age, person(Person, Age), People), % Include age
findall(Food-Health, food(Food, Health), Foods), % Include health factor
length(People, NumberOfPeople),
length(Foods, NumberOfFoods),
NumberOfPeople =< NumberOfFoods,
person_food_pairing(People, Foods, PeopleFoodPairings).
person_food_pairing([], _, []).
person_food_pairing(People, Foods, [Person-Food|RemainingPairs]) :-
select(Person-Age, People, RemainingPeople), % Select person-age pair
select(Food-Health, Foods, RemainingFoods), % Select food-health pair
(Age < 20 -> Health == good ; true), % Condition to include
person_food_pairing(RemainingPeople, RemainingFoods, RemainingPairs).
请注意此处使用==/2
而不是统一=/2
。原因是您希望_
与good
不匹配。如果使用统一,则Prolog将成功将变量_
与原子good
统一起来。另一方面,==/2
检查这两个术语是否真的相同且不统一。