如何在prolog中只显示一个结果?

时间:2016-05-12 11:02:36

标签: prolog

数据:

%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是主键,我只能使用。 ,+< > < => =

2 个答案:

答案 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或其他地方找到一个很好的参考,请发表评论。