数据:
%flight(FID, Start, Destination, Company, Seats).
%------------------------------------------------------
flight(1, 'Paris', 'Berlin', 'Lufthansa', 210).
flight(2, 'Frankfurt', 'Dubai', 'Lufthansa', 400).
flight(3, 'Rome', 'Barcelona', 'Eurowings', 350).
我想知道所有拥有超过200个座位的航班的公司。但每家公司只应退回一次。
我试过了:
q1(Company) :- flight(_, _, _, Company, S), S > 200.
但这会两次让汉莎航空失效。我试过了:
q1(Company) :- flight(_, _, _, Company, S), S > 200,!.
但这是在德国汉莎航空公司首次返回后退出的。我想我必须在子查询中包装条件:
q1(Company) :- flight(_, _, _, Company, S), q12(S).
q12(S) :- flight(_, _, _, _, S), S > 200,!.
但这也是在第一次回归后退出的。知道如何使用cut来返回只匹配一次的公司吗?
FID是主键,我只能使用。 ,+< > < => =
答案 0 :(得分:3)
正如我在评论中所说,实现此目的的一种方法是使用setof/3
获取结果的排序列表不重复,例如:
?- setof(C, q1(C), Cs).
这是一种推荐方法,可以删除多余的解决方案。您可以枚举此类解决方案,例如:
?- setof(C, q1(C), Cs), member(C, Cs).
建议观众自行决定剩下的......
还有几种方法可以解决这个问题,即脑力受损的情况,而不熟练的教练可能会强加给你。例如,以下是使用setof/3
获取所有公司的所有公司的无效且高度非惯用的方法
companies(Cs) :- companies_([], Cs). companies_(Cs0, Cs) :- ( flight(_, _, _, C, _), \+ memberchk(C, Cs0) -> companies_([C|Cs0], Cs) ; Cs0 = Cs ).
我没有胃可以进一步携带这个,所以我只是以你的提示结束:你只需要插入一个目标来解决你的任务。我希望你的老师对这个“解决方案”感到满意。
答案 1 :(得分:2)
这里的关键是唯一ID。你原来的问题是:
哪些公司的航班超过200个席位?
查询很明显:
?- flight(_,_,_,C,S), S > 200.
C = 'Lufthansa',
S = 210 ;
C = 'Lufthansa',
S = 400 ;
C = 'Eurowings',
S = 350.
现在,由于这些ID是唯一的,因此组内的航班将与同一公司和座位相同> 200具有最高(或最低)ID。因此,您可以将您的问题重新制定为:
哪些航班有超过200个座位,且同一公司的航班组中的最高ID?
或者,为了使我们能够更接近我们在Prolog中提出查询的方式,
如果乘坐有ID,公司和座位的航班,座位必须超过200个,并且必须没有其他航班来自同一家公司且ID更高。
?- flight(ID,_,_,C,S), S > 200, \+ ( flight(IDX,_,_,C,_), IDX > ID ).
ID = 2,
C = 'Lufthansa',
S = 400 ;
ID = 3,
C = 'Eurowings',
S = 350.
如果您将此查询放在谓词中,则可以避免报告ID和实际席位数。
顺便说一句,这种方法是this answer对某种相关问题(无耻的自我推销)的礼貌。我真的无法记住我的想法:我确信自己并没有想出来。如果有人可以在Stackoverflow或其他地方找到一个很好的参考,请发表评论。