首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >配对团队

配对团队
EN

Stack Overflow用户
提问于 2013-03-02 14:05:17
回答 2查看 273关注 0票数 0

数据库包含团队列表,每个团队都按位置分隔(西部团队、东部团队等)。有两种类型的事实来描述这一点。团队(TeamNumber,Losses)和区域(TeamNumber,Region)。例如:

代码语言:javascript
复制
team(1, 10).
team(2, 11).
team(3, 12).
team(4, 13).

region(1, east).
region(2, west).
region(3, east).
region(4, southeast).

注意:团队列表并不总是从损失最少到损失最多的顺序排列。

我正在尝试将一组团队配对在一起,以便将损失最高的团队与损失最低的团队配对,然后将损失第二高的团队与损失第二少的团队配对,然后将ecetera ecetera配对。规则是,在相同区域内配对团队是优先事项。在上面的示例中,团队3和1将配对在一起,因为他们都是东部团队。现在,剩下的团队是团队2和团队4。但因为没有其他团队在他们的区域内,团队2和团队4相互匹配。

现在,我在想我可以写什么函数来配对团队。我已经编写了一个函数,将一个区域内的所有不同团队分组到一个相应的列表中。我还编写了一个函数来获取最小值和最大值(最高和最低损失)。

我如何编写一个函数来将同一区域内的所有团队配对,然后创建一个新的列表来粘贴该列表中的所有剩余团队?

EN

回答 2

Stack Overflow用户

发布于 2013-03-04 12:13:13

我还写了一个函数来得到最小值和最大值(最高和最低损失)。

Prolog和其他声明性语言在一些令人惊讶的方面与过程性语言不同,其中之一是经常做一点工作,期望在某种循环构造中重用它,这并不完全是正确的方法。这在SQL中更为明显,在SQL中,您应该始终处理集合,但在Prolog中也是如此,在Prolog中,我们拥有的少量显式循环构造并未大量使用。

在程序环境中匹配低分和高分团队的问题最好通过如下过程来解决:

代码语言:javascript
复制
def match(teams):
  while we have teams:
    remove the lowest scoring team from teams
    remove the highest scoring team from teams
    save this pair
  return the list of pairs

一种使其更具功能性的天真方法是使用递归:

代码语言:javascript
复制
def match(teams):
  if teams is empty: return empty list
  otherwise:
    remove the lowest scoring team
    remove the highest scoring team
    return this pair appended to match(teams without these two items)

实际上,你可以不费很多力气就把它转换成看起来合理的Prolog:

代码语言:javascript
复制
match([], []).
match(Teams, [Lowest-Highest|Pairs]) :-
  lowest(Teams, Lowest),
  highest(Teams, Highest),
  select(Lowest, Teams, TeamsWithoutLowest),
  select(Highest, TeamsWithoutLowest, RemainingTeams),
  match(RemainingTeams, Pairs).

这不太可能是高效的,因为在select/3中有许多重复的列表扫描和大量的列表重建正在进行,但它可能更具声明性。

另一种方法是对团队列表进行排序,然后将其折叠起来,以获得最低和最高的配对。视觉上:

代码语言:javascript
复制
[1, 2, 3, 4, 5, 6]
[1, 2, 3],  [4, 5, 6]
[1, 2, 3],  [6, 5, 4]

[1,     2,     3]
[6,     5,     4]
-------------------
[1-6], [2-5], [3-4]

我们可以直接在Prolog中做这件事,但首先我们需要一种将两个列表配对的方法:

代码语言:javascript
复制
pair_off([], _, []).
pair_off([L|Ls], [R|Rs], [L-R|Rest]) :- pair_off(Ls, Rs, Rest).

然后算法转到Prolog,如下所示:

代码语言:javascript
复制
match_lowest_highest(SortedList, Pairs) :-
  length(SortedList, N2),
  N is N2 div 2,
  length(TopHalf, N),
  append(TopHalf, BottomHalf, SortedList),
  reverse(BottomHalf, BottomHalfFlipped),
  pair_off(TopHalf, BottomHalfFlipped, Pairs).

这仍然不是很有效,但reverse/2内置可能正在使用差异列表,所以它应该不会太昂贵;通过将append/3与已实体化的未知数列表一起使用,我们节省了一大堆临时列表构造,这些构造可能会被丢弃。因此,我不认为这是非常低效的,但我相信有其他方法可以做到这一点会更有效率。

票数 2
EN

Stack Overflow用户

发布于 2013-03-02 19:01:29

好吧,我试过了。我认为all_ teams _ paired /2将提供您所描述的所有配对的团队的列表,以及剩余的团队(如果有奇数个团队)。

代码语言:javascript
复制
% list of all regions
regions(Regions) :- 
    findall(Region, region(_, Region), UnsortedRegions),
    sort(UnsortedRegions, Regions).

% list of all teams in a region
teams_in_region(Region, Teams) :- findall(Team, (team(Team, _), region(Team, Region)), Teams).

% bottom team in a list
bottom_team(TeamList, BottomTeam) :-
    member(BottomTeam, TeamList),
    findall(Losses, (team(Team, Losses), member(Team, TeamList)), AllLosses),
    team(BottomTeam, Losses),
    min_member(Losses, AllLosses).

% top team in a list
top_team(TeamList, TopTeam) :-
    member(TopTeam, TeamList),
    findall(Losses, (member(Team, TeamList), team(Team, Losses)), AllLosses),
    team(TopTeam, Losses),
    max_member(Losses, AllLosses).

% teams are paired with the top loser playing the bottom loser and there can be a leftover
%  if there is an odd number of teams
paired_teams([], [], []).
paired_teams([LonelyTeam], [], [LonelyTeam]).
paired_teams(TeamList, PairedTeams, UnpairedTeam) :-
    top_team(TeamList, TopTeam),
    bottom_team(TeamList, BottomTeam),
    TopTeam \= BottomTeam,
    subtract(TeamList, [TopTeam, BottomTeam], RemainingTeams),
    paired_teams(RemainingTeams, RemainingPairedTeams, UnpairedTeam),
    append([TopTeam-BottomTeam], RemainingPairedTeams, PairedTeams).

% a list of regions has an associated list of paired teams and leftover teams
region_paired_teams([], [], []).
region_paired_teams(Regions, PairedTeams, UnpairedTeams) :-
    Regions = [Region|RemainingRegions],
    teams_in_region(Region, TeamList),
    paired_teams(TeamList, RegionPairedTeams, RegionUnpairedTeam),
    region_paired_teams(RemainingRegions, RemainingPairedTeams, RemainingUnpairedTeams),
    append(RegionPairedTeams, RemainingPairedTeams, PairedTeams),
    append(RegionUnpairedTeam, RemainingUnpairedTeams, UnpairedTeams).

% a list of all teams paired with priority given to region and a leftover team (if any)
all_teams_paired(TeamsPaired, Leftover) :-
    regions(Regions),
    region_paired_teams(Regions, RegionPairedTeams, UnpairedTeams),
    paired_teams(UnpairedTeams, NonRegionPairedTeams, Leftover),
    append(RegionPairedTeams, NonRegionPairedTeams, TeamsPaired).

我是否正确理解了您的要求?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15171357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档