2016-05-15 54 views
0

我一直在學習考試時遇到過去的紙質問題。Prolog - 使用Bagof

的問題是:

https://gyazo.com/ee2fcd88d67068e8cf7d478a98f486a0

我想我必須使用findall/bagof/setof因爲我需要收集一套解決方案。此外,setof似乎是合適的,因爲該列表需要按降序呈現。

我的解決方案迄今:

teams(List) :- 
    setof((Team, A), 
    (Team^team(Team, _, Wins, Draws, _), A is Wins*3 + Draws*1), 
    List). 

但問題是我不完全得到的答案都在一個列表中。我很可能錯誤地使用Team ^。我真的很感謝關於如何從點獲得有序元組列表的指針。它給我的輸出是:

X = [(queenspark,43)] ? ; 
X = [(stirling,26)] ? ; 
X = [(clyde,25)] ? ; 
X = [(peterhead,35)] ? ; 
X = [(rangers,63)] ? ; 

而且,它不是真正明顯的是什麼樣的順序,如果有它在,所以我也失去了對如何setof被訂購。

什麼是使用setof來處理這個問題的最好方法?

謝謝。

回答

3

首先,我建議將(Team,A)更改爲A-Team的配對代表A-Team,因爲這是團隊的總分,因此這是您要用於排序的關鍵。然後,您希望將不應包含在列表中的變量作爲要聚合的查詢前面的^的前綴。請看下面的例子:

?- setof(A-Team, P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1), List). 
List = [25-clyde,26-stirling,35-peterhead,43-queenspark,63-rangers] 

既然你這麼問,考慮下面的查詢與對排序翻轉Team-A用於比較的原因:

?- setof(Team-A,P^Wins^Draws^L^(team(Team,P,Wins,Draws,L), A is Wins*3 + Draws*1),List). 
List = [clyde-25,peterhead-35,queenspark-43,rangers-63,stirling-26] 

現在結果列表關於teamnames排序。所以A-Team是合適的選擇。然後,您可以使用謂詞列表:reverse/2將順序反轉爲降序列表,然後定義輔助句謂語pair_second/2,您可以在apply:maplist/3中使用以排除對中的前導分數:

:- use_module(library(lists)). 
:- use_module(library(apply)). 

% team(+Name, +Played, +Won, +Drawn, +Lost) 
team(clyde,26,7,4,15). 
team(peterhead,26,9,8,9). 
team(queenspark,24,12,7,5). 
team(rangers,26,19,6,1). 
team(stirling,25,7,5,13). 

pair_second(A-B,B). % 2nd argument is 2nd element of pair 

teams(Results) :- 
    setof(A-Team, 
     P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1), 
     List), 
    reverse(List,RList), 
    maplist(pair_second,RList,Results). % apply pair_second/2 to RList 

如果你現在查詢謂詞你得到想要的結果:

?- teams(T). 
T = [rangers,queenspark,peterhead,stirling,clyde] 

關於在評論你的問題:是的,當然這是可能的。您可以編寫一個謂詞,該謂詞描述對的列表與列表之間的關係,而不僅僅包含對的第二個元素。讓我們把它pairlist_namelist/2:

pairlist_namelist([],[]). 
pairlist_namelist([S-N|SNs],[N|Ns]) :- 
    pairlist_namelist(SNs,Ns). 

然後你就可以定義團隊/ 1,像這樣:

teams(Results) :- 
    setof(A-Team, 
     P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1), 
     List), 
    reverse(List,RList), 
    pairlist_namelist(RList,Results). 

在這種情況下,除了MAPLIST/3,你不需要任何pair_second/2。此外,您不需要包含:- use_module(library(apply)).上面的示例查詢與此版本的結果相同。

+0

感謝您的支持!有沒有辦法做到這個問題,而不使用maplist?它不是真的出現在我們的講座幻燈片中(我們正在按照Learn Prolog Now),所以我不確定考試是否會被允許。我們絕對不能在考試中使用外部模塊,這是肯定的。 – user3186023

+0

我從你的代碼中獲得靈感。非常感謝您使用「A-B」教給我的整潔技巧!不知道這是可能的,使排序更容易。再次感謝。 – user3186023

+0

@ user3186023:我更新了我的答案以解決您的問題;-) – tas