Prolog - 使用Bagof

时间:2016-05-15 14:19:06

标签: prolog prolog-setof

在考试期间,我一直被困在过去的纸质问题上。

问题是:

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处理此问题的最佳方法是什么?

感谢。

1 个答案:

答案 0 :(得分:2)

首先,我建议将(Team,A)更改为配对代表A-Team,前面有A,因为这是团队的总分,因此是您想要的关键字用于分类。然后,您希望在不希望列在列表中的变量前加上要聚合的查询前面的^。请参阅以下示例:

   ?- 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]

现在,结果列表将根据团队名称进行排序。所以A-Team是合适的选择。然后,您可以使用谓词列表:reverse / 2将顺序反转为降序列表,然后定义辅助谓词pair_second / 2,您可以使用apply:maplist / 3来消除成对中的主要分数:< / p>

:- 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)).上面的示例查询会产生与此版本相同的结果。