在整场比赛中获得两支球队最大的领先优势
Get two teams greatest lead throughout game
我有一个涉及 2 个团队的 Game
。 Game
有一个 ScoreEvents
的列表。每个 ScoreEvent 对于得分的团队来说都是 1 分。我需要知道每个团队的最大领先分数是多少(如果他们从未领先过则为 0)。 ScoreEvents
列表按 TimeSinceStart
.
排序
public class ScoreEvent
{
public int TeamId { get; set; }
public TimeSpan TimeSinceStart { get; set; }
}
public void GetMaxScoreLead()
{
var ScoreEvents = new List<ScoreEvent>
{
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(100)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(200)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(300)},
//Score at 300 ticks is 3-0 to TeamdId = 0
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(400)},
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(500)},
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(600)},
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(700)},
//Score at 700 ticks is a 3-4 to TeamId = 1
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(800)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(900)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(1000)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(1100)}
//Score at 1100 ticks is 7-4 to TeamId 0
};
}
因此对于上面的示例,每个团队最大领先的答案是:
- TeamId (0) = 3 最大领先
- TeamId (1) = 1 最大领先
编辑:我必须的代码。我知道我需要在某处跟踪当前分数。
var teamZeroLargestLead = 0;
var teamOneLargestLead = 0;
var internalTeamZeroLargestLead = 0;
var internalTeamOneLargestLead = 0;
foreach (var scoreEvent in scoreEvents.OrderBy(x => x.TimeSinceStart))
{
if (scoreEvent.TeamId == 0)
{
if (internalTeamOneLargestLead > teamOneLargestLead)
{
teamOneLargestLead = internalTeamOneLargestLead;
internalTeamOneLargestLead = 0;
}
internalTeamZeroLargestLead += 1;
}
else
{
if(internalTeamZeroLargestLead > teamZeroLargestLead)
{
teamZeroLargestLead = internalTeamZeroLargestLead;
internalTeamZeroLargestLead = 0;
}
internalTeamOneLargestLead += 1;
}
}
var leftTeamId = ScoreEvents.First().TeamId
var res = ScoreEvents
.OrderBy(x => x.TimeSinceStart)
.Aggregate(
(max: 0, min: 0, curr: 0),
(acc, currSE) => {
var curr = currSE.TeamId == leftTeamId
? acc.curr +1
: acc.curr - 1;
if(curr > acc.max)
{
return (curr, acc.min, curr);
}
else if (curr < acc.min)
{
return (acc.max, curr, curr);
}
return (acc.max, acc.min, curr);
});
对于 ID 为 leftTeamId
的 "left" 团队,您使用 res.max
,对于 "right" 团队,您使用 Math.Abs(res.min)
:
- TeamId (0) =
res.max
最大领先优势
- TeamId (1) =
Math.Abs(res.min)
最大领先
我没有得到正确的 TeamId,因为理论上只有一支球队可以得分(但假设至少有一支球队得分 =)。
由于只有两个团队,看看这个方法是否满足您的需求。
int team1Score = 0;
int team2Score = 0;
int maximumLead = 0;
int maximumLeadTeamId = -1;
for (int i = 0; i < ScoreEvents.Count; i++)
{
if (ScoreEvents[i].TeamId == 0)
{
team1Score++;
}
else
{
team2Score++;
}
int currentLead = Math.Abs(team1Score - team2Score);
if (currentLead > maximumLead)
{
maximumLead = currentLead;
maximumLeadTeamId = ScoreEvents[i].TeamId;
}
}
maximumLeadTeamId 为整场比赛中领先最大的球队的Id,maximumLead 为两队的最大进球差。
您可以使用它来获取在指定时间跨度得分的球队 ID 的字典:
public static Dictionary<int, int> GetMaxScoreLead(IEnumerable<ScoreEvent> scoreEvents, TimeSpan time)
{
var scoreDictionary = new Dictionary<int, int>();
var grouping = scoreEvents.Where(e => e.TimeSinceStart <= time).GroupBy(e => e.TeamId);
foreach (var group in grouping)
{
scoreDictionary.Add(group.Key, group.Count());
}
return scoreDictionary;
}
此代码不依赖于团队的数量。您可以从这个字典结构中轻松确定获胜团队。例如:
var winningTeam = getScores.OrderByDescending(x => x.Value).FirstOrDefault();
我用 foreach
循环稍微更新和简化了你的算法,现在 returns 正确的结果 - teamZeroLead
是 3
,teamOneLead
是 1
.
var teamZeroLead = 0;
var teamOneLead = 0;
var teamZeroScore = 0;
var teamOneScore = 0;
foreach (var scoreEvent in scoreEvents.OrderBy(x => x.TimeSinceStart))
{
if (scoreEvent.TeamId == 0)
{
teamZeroScore++;
teamZeroLead = Math.Max(teamZeroLead, teamZeroScore - teamOneScore);
}
else
{
teamOneScore++;
teamOneLead = Math.Max(teamOneLead, teamOneScore - teamZeroScore);
}
}
在每次循环迭代中,您都在计算每个团队的当前分数,然后计算领先值并将其分配给结果值(如果它大于之前计算的值)。
同样的逻辑可以用Aggregate
方法和值元组来写,你可以选择对你来说更易读和方便的
var result = scoreEvents.Aggregate((teamZeroLead: 0, teamOneLead: 0, teamZeroScore: 0, teamOneScore: 0),
(scores, scoreEvent) =>
{
if (scoreEvent.TeamId == 0)
{
scores.teamZeroScore++;
scores.teamZeroLead = Math.Max(scores.teamZeroLead, scores.teamZeroScore - scores.teamOneScore);
}
else
{
scores.teamOneScore++;
scores.teamOneLead = Math.Max(scores.teamOneLead, scores.teamOneScore - scores.teamZeroScore);
}
return scores;
});
执行后你可以使用result.teamZeroLead
和result.teamOneLead
得到结果值
我有一个涉及 2 个团队的 Game
。 Game
有一个 ScoreEvents
的列表。每个 ScoreEvent 对于得分的团队来说都是 1 分。我需要知道每个团队的最大领先分数是多少(如果他们从未领先过则为 0)。 ScoreEvents
列表按 TimeSinceStart
.
public class ScoreEvent
{
public int TeamId { get; set; }
public TimeSpan TimeSinceStart { get; set; }
}
public void GetMaxScoreLead()
{
var ScoreEvents = new List<ScoreEvent>
{
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(100)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(200)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(300)},
//Score at 300 ticks is 3-0 to TeamdId = 0
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(400)},
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(500)},
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(600)},
new ScoreEvent { TeamId = 1, TimeSinceStart = new TimeSpan(700)},
//Score at 700 ticks is a 3-4 to TeamId = 1
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(800)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(900)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(1000)},
new ScoreEvent { TeamId = 0, TimeSinceStart = new TimeSpan(1100)}
//Score at 1100 ticks is 7-4 to TeamId 0
};
}
因此对于上面的示例,每个团队最大领先的答案是:
- TeamId (0) = 3 最大领先
- TeamId (1) = 1 最大领先
编辑:我必须的代码。我知道我需要在某处跟踪当前分数。
var teamZeroLargestLead = 0;
var teamOneLargestLead = 0;
var internalTeamZeroLargestLead = 0;
var internalTeamOneLargestLead = 0;
foreach (var scoreEvent in scoreEvents.OrderBy(x => x.TimeSinceStart))
{
if (scoreEvent.TeamId == 0)
{
if (internalTeamOneLargestLead > teamOneLargestLead)
{
teamOneLargestLead = internalTeamOneLargestLead;
internalTeamOneLargestLead = 0;
}
internalTeamZeroLargestLead += 1;
}
else
{
if(internalTeamZeroLargestLead > teamZeroLargestLead)
{
teamZeroLargestLead = internalTeamZeroLargestLead;
internalTeamZeroLargestLead = 0;
}
internalTeamOneLargestLead += 1;
}
}
var leftTeamId = ScoreEvents.First().TeamId
var res = ScoreEvents
.OrderBy(x => x.TimeSinceStart)
.Aggregate(
(max: 0, min: 0, curr: 0),
(acc, currSE) => {
var curr = currSE.TeamId == leftTeamId
? acc.curr +1
: acc.curr - 1;
if(curr > acc.max)
{
return (curr, acc.min, curr);
}
else if (curr < acc.min)
{
return (acc.max, curr, curr);
}
return (acc.max, acc.min, curr);
});
对于 ID 为 leftTeamId
的 "left" 团队,您使用 res.max
,对于 "right" 团队,您使用 Math.Abs(res.min)
:
- TeamId (0) =
res.max
最大领先优势 - TeamId (1) =
Math.Abs(res.min)
最大领先
我没有得到正确的 TeamId,因为理论上只有一支球队可以得分(但假设至少有一支球队得分 =)。
由于只有两个团队,看看这个方法是否满足您的需求。
int team1Score = 0;
int team2Score = 0;
int maximumLead = 0;
int maximumLeadTeamId = -1;
for (int i = 0; i < ScoreEvents.Count; i++)
{
if (ScoreEvents[i].TeamId == 0)
{
team1Score++;
}
else
{
team2Score++;
}
int currentLead = Math.Abs(team1Score - team2Score);
if (currentLead > maximumLead)
{
maximumLead = currentLead;
maximumLeadTeamId = ScoreEvents[i].TeamId;
}
}
maximumLeadTeamId 为整场比赛中领先最大的球队的Id,maximumLead 为两队的最大进球差。
您可以使用它来获取在指定时间跨度得分的球队 ID 的字典:
public static Dictionary<int, int> GetMaxScoreLead(IEnumerable<ScoreEvent> scoreEvents, TimeSpan time)
{
var scoreDictionary = new Dictionary<int, int>();
var grouping = scoreEvents.Where(e => e.TimeSinceStart <= time).GroupBy(e => e.TeamId);
foreach (var group in grouping)
{
scoreDictionary.Add(group.Key, group.Count());
}
return scoreDictionary;
}
此代码不依赖于团队的数量。您可以从这个字典结构中轻松确定获胜团队。例如:
var winningTeam = getScores.OrderByDescending(x => x.Value).FirstOrDefault();
我用 foreach
循环稍微更新和简化了你的算法,现在 returns 正确的结果 - teamZeroLead
是 3
,teamOneLead
是 1
.
var teamZeroLead = 0;
var teamOneLead = 0;
var teamZeroScore = 0;
var teamOneScore = 0;
foreach (var scoreEvent in scoreEvents.OrderBy(x => x.TimeSinceStart))
{
if (scoreEvent.TeamId == 0)
{
teamZeroScore++;
teamZeroLead = Math.Max(teamZeroLead, teamZeroScore - teamOneScore);
}
else
{
teamOneScore++;
teamOneLead = Math.Max(teamOneLead, teamOneScore - teamZeroScore);
}
}
在每次循环迭代中,您都在计算每个团队的当前分数,然后计算领先值并将其分配给结果值(如果它大于之前计算的值)。
同样的逻辑可以用Aggregate
方法和值元组来写,你可以选择对你来说更易读和方便的
var result = scoreEvents.Aggregate((teamZeroLead: 0, teamOneLead: 0, teamZeroScore: 0, teamOneScore: 0),
(scores, scoreEvent) =>
{
if (scoreEvent.TeamId == 0)
{
scores.teamZeroScore++;
scores.teamZeroLead = Math.Max(scores.teamZeroLead, scores.teamZeroScore - scores.teamOneScore);
}
else
{
scores.teamOneScore++;
scores.teamOneLead = Math.Max(scores.teamOneLead, scores.teamOneScore - scores.teamZeroScore);
}
return scores;
});
执行后你可以使用result.teamZeroLead
和result.teamOneLead