2016-05-12 8 views
1

データ:プロローグに1つの結果だけを表示する方法は?

%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,!. 

しかし、これはまた、最初のリターン後も終了しました。カットを使って一度だけ一致する会社をどうやって返すことができるか考えてみましょうか?

FIDがプライマリキーで、私は使用が許可されています。 、+ <> < => =

+2

まず、 '!/ 0'を削除します:プログラムの意図した意味を破壊します。次に、 '? - setof(Company、q1(Company)、Cs) 'のように' setof/3'を使ってすべての企業を集めます。これは、重複のないソートされたリストを提供します。あなたが望むなら、 '? - setof(C、q1(C)、Cs)、member(C、Cs) 'のように会社を列挙することができます。 – mat

+0

@mat setof、just"を使用することはできません。 !\ + < ><= > = " –

+2

これは奇妙な要件です。少なくとも 'sort/2'を使用できますか?それ以外の場合は、SQL left joinなどの趣旨で変なトリックを行う必要があります。 –

答えて

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があるのですか?我々はプロローグでクエリを提起することができる方法にもう少し近い場合にする

または、

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または他の場所で良いリファレンスを見つけることができますコメントしてください。

+0

私は正しい軌道に乗ってくれてありがとう。 BTW私はカットオペレータを使用して正しいように見える別のソリューションを発見した。私はそれを私の質問に入れました。 –

+0

@artworkadシ本当にカットが必要ですか?それを削除するとどうなりますか? –

+0

はい他の場合はdupsがあります –

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

これは 'memberchk/2'を使用していますが、おそらくは"許可され​​ていません ")。代わりの方法については他の答えを見てください。 –

+3

このバージョンのすべては、表示されているプリミティブのみを使用して簡単に表現できます。たとえば、 'memberchk/2'とif-then-elseは'!/ 0'で表現できます。これらはすべてロジック*ハッキング*の例であり、ロジック*プログラミング*の例ではありませんので、この方向でさらに詳しく説明したくありません。 – mat

+0

「memberchk/2」はなぜですか? – false

関連する問題