C# 从球员各位置的得分列表中查找可能的最大总得分
如果有一份球员名单,我如何找到球队的最高得分 我维护一个社交幻想联盟(澳大利亚规则)网站,在那里你可以在赛季开始时挑选18名球员,然后每周你选择一支由6名球员组成的球队,每个位置分配一名球员。您本周的得分是您选择的每个球员得分的总和。例如,如果每个球员得分50分,你的球队本周得分将为300分 为了在回合结束后分析您的团队,我想展示几个指标。第一个是每个位置的最高得分,第二个是本周的团队 我可以通过这样的操作计算出每个位置的最高分数(“球员分数列表”屏幕截图中的绿色突出显示) 然而,要计算出球队可能取得的最大得分比我想象的要困难得多。在这种情况下,各职位之间可能会分享高分。此外,你可能选择的“最好的球队”可能并不意味着该球员在某个位置的得分最高 在这个例子中,我计算出的该队的最佳得分(即每个位置上你可以挑选的最佳6名球员)是288。也就是说,将我在红色方框中突出显示的6个分数相加,得出288分。看看即使乔希·肯尼迪在“关”的位置上得了57分,你还是选择他在“FW”的位置更好,因为下一个最好的“FW”球员得分19分(托比·格林的)是23分请记住,在回合开始之前,您必须将一名球员分配到一个位置,这样您只能使用每个球员的一个分数。 有什么建议吗?我如何编写一个循环/查询,以提取球员列表和他们的得分,从而构成尽可能最好的团队得分288 为了获得更多信息,playerList是这样构建的,稍后我会在一些web服务调用之后添加实际分数,这些调用会获得统计数据(踢、手球等)C# 从球员各位置的得分列表中查找可能的最大总得分,c#,linq,C#,Linq,如果有一份球员名单,我如何找到球队的最高得分 我维护一个社交幻想联盟(澳大利亚规则)网站,在那里你可以在赛季开始时挑选18名球员,然后每周你选择一支由6名球员组成的球队,每个位置分配一名球员。您本周的得分是您选择的每个球员得分的总和。例如,如果每个球员得分50分,你的球队本周得分将为300分 为了在回合结束后分析您的团队,我想展示几个指标。第一个是每个位置的最高得分,第二个是本周的团队 我可以通过这样的操作计算出每个位置的最高分数(“球员分数列表”屏幕截图中的绿色突出显示) 然而,要计算出球队可
List playerList=new List();
foreach(团队中的var t)
{
playerList.AddRange(t.TeamSelections.Where(x=>x.DateInactive==null).OrderBy(x=>x.PlayerName).Select(p=>newplayerscore
{
TeamId=p.TeamId,
PlayerName=p.PlayerName,
俱乐部,
ClubAbbreviation=Helper.Stats.GetClubAbbreviation(p.Club),
TeamLeagueId=p.Team.LeagueId,
TeamSelection=p.TeamSelectionId
}));
}
我不知道如何挑选团队的规则,但大概六个角色中每一个都必须有一个玩家
如果你没有太多的玩家(例如,在上面的表格中,它可能会很有效),那么蛮力方法可能会奏效
然后,如果你有n个
玩家,第一个玩家有n个
选择,第二个玩家有n-1个
(因为你不能让同一个玩家在两个不同的位置),等等。这就提供了总共nP6
()的可能性。这是相当大的,数量级为n⁶代码>。
如果你想实现这一点,你可以快速而肮脏地实现一个六个深度的循环(确保排除已经选择的玩家),检查分数,并跟踪最高的一个(s)
减少检查可能性的一种方法,我认为这是合理的,就是:只从该位置前6名得分手中选择你在X位置的球员。直觉是这样的:如果我为我的其他位置选择了(最佳或不最佳)5名球员,我不可能为位置X选择所有6名最佳得分手!因此,至少有一个仍然可用。那我就只能从剩下的最好的中挑一个了。所以我当然可以排除那些没有进入前6名的人。当存在联系时,可能会出现问题,在这种情况下,出于安全考虑,任何与前6名中的任何一个职位有联系的人都可以留任
这样(假设没有关系),您只需搜索6即可⁶代码>可能性,最多(如果同一玩家在不同类别中获得前6名,则可能性较小)。而且,即使是对于一个大的列表,最初对前6名的搜索也很容易处理
所有这些都可以用LINQ来完成,但不需要这样做。所以这里就是它的结局。。可能有助于任何人在一组数字中选择尽可能高的总数。到目前为止,我还没有看到一个实例不能返回正确的结果。。请随意建议代码清理/优化
private static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
{
return length == 1 ? list.Select(t => new[] {t}) : GetPermutations(list, length - 1).SelectMany(t => list.Where(o => !t.Contains(o)), (t1, t2) => t1.Concat(new[] {t2}));
}
public static List<PlayerScore> TeamOfTheWeek(List<PlayerScore> playerList)
{
// Remove the players who scored 0 accross the board.
playerList.RemoveAll(player => player.Forward + player.TallForward + player.Offensive + player.Defensive + player.OnBaller + player.Ruck == 0);
// Rank each player score within a position.
var forwardRank = playerList.RankByDescending(p => p.Forward, (p, r) => new {Rank = r, Player = p});
var tallForwardRank = playerList.RankByDescending(p => p.TallForward, (p, r) => new {Rank = r, Player = p});
var offensiveRank = playerList.RankByDescending(p => p.Offensive, (p, r) => new { Rank = r, Player = p });
var defensiveRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
var onBallerRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
var ruckRank = playerList.RankByDescending(p => p.Ruck, (p, r) => new { Rank = r, Player = p });
for (int i = playerList.Count - 1; i >= 0; i--)
{
//var rankName = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Player.PlayerName;
var fw = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var tf = tallForwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var off = offensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var def = defensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var ob = onBallerRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var ruck = ruckRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
if (fw >= 6 && tf >= 6 && off >= 6 && def >= 6 && ob >= 6 && ruck >= 6)
{
// Player is outside top 6 for each position so remove, and reduce permutations.
playerList.RemoveAt(i);
}
}
// Now update the playerId as this is used to join back to the array later.
var playerId = 0;
foreach (var p in playerList.OrderBy(p => p.PlayerName))
{
p.Id = playerId;
playerId = playerId + 1;
}
// Create and fill the position scores.
List<int[]> positionScoreArray = new List<int[]>();
foreach (var player in playerList.OrderBy(p => p.PlayerName))
{
// Player scored more than 0 so add to the positionScoreArray.
int[] playerScores = { player.Forward, player.TallForward, player.Offensive, player.Defensive, player.OnBaller, player.Ruck };
positionScoreArray.Add(playerScores);
}
// Players remaining in list pulled into array, ready for processing.
string[] playerNameArray = playerList.OrderBy(x => x.PlayerName).Select(p => p.PlayerName).ToArray();
// Load up the actual position scores to use in Parallel.For processing.
for (int i = 0; i < playerNameArray.Length; i++)
{
for (int j = 0; j < positionScoreArray.Count; j++)
{
if (j == 0)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Forward;
}
if (j == 1)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.TallForward;
}
if (j == 2)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Offensive;
}
if (j == 3)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Defensive;
}
if (j == 4)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.OnBaller;
}
if (j == 5)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Ruck;
}
}
}
Stopwatch parallelForEachStopWatch = new Stopwatch();
parallelForEachStopWatch.Start();
var count = 0;
var playerIds = Enumerable.Range(0, playerNameArray.Length).ToList();
var best = new { PlayerIds = new List<int>(), TeamScore = 0 };
var positions = new[] { "FW", "TF", "Off", "Def", "OB", "Ruck" };
// Thread safe the Parallel.ForEach
lock (ThreadSafeObject)
{
Parallel.ForEach(GetPermutations(playerIds, positions.Length), perm =>
{
var teamScore = 0;
var players = perm.ToList();
for (int i = 0; i < positions.Length; i++) teamScore += positionScoreArray[players[i]][i];
if (teamScore > best.TeamScore) best = new {PlayerIds = players, TeamScore = teamScore};
if (count++%100000 == 0) Debug.WriteLine($"{count - 1:n0}");
}
);
}
parallelForEachStopWatch.Stop();
TimeSpan parallelForEach = parallelForEachStopWatch.Elapsed;
Debug.WriteLine($"Parallel.ForEach (secs): {parallelForEach.Seconds}");
Debug.WriteLine($"Permutations: {count:n0}");
Debug.WriteLine($"Team Score: {best.TeamScore}");
// Track Parallel.ForEach result.
var tcTotwRequest = new TelemetryClient();
tcTotwRequest.TrackEvent($"Permutations: {count:n0} Score: {best.TeamScore} Time (sec): {parallelForEach.Seconds}");
lock (ThreadSafeObject)
{
if (best.PlayerIds.Count > 0)
{
for (int i = 0; i < positions.Length; i++)
{
// Update the playerList, marking best players with TeamOfTheWeek position.
var player = playerList.FirstOrDefault(p => p.Id == best.PlayerIds[i]);
if (player != null)
{
player.TeamOfTheWeekPosition = positions[i];
player.TeamOfTheWeekScore = best.TeamScore;
}
}
}
}
return playerList.OrderBy(p => p.PlayerName).ToList();
}
}
私有静态IEnumerable GetPermutations(IEnumerable列表,int-length)
{
返回长度==1?list.Select(t=>new[]{t}):GetPermutations(list,length-1)。SelectMany(t=>list.Where(o=>!t.Contains(o)),(t1,t2)=>t1.Concat(new[]{t2});
}
每周的公共静态列表(列表播放列表)
{
//移除棋盘上得分为0的玩家。
playerList.RemoveAll(player=>player.Forward+player.TallForward+player.进攻+player.防守+player.OnBaller+player.Ruck==0);
//在一个位置内对每个球员的得分进行排名。
var forwardRank=playerList.RankByDescending(p=>p.Forward,(p,r)=>new{Rank=r,Player=p});
var tallForwardRank=playerList.RankByDescending(p=>p.TallForward,(p,r)=>new{Rank=r,Player=p});
var offensiveRank=玩家列表。Rankbydesking(p=>p.进攻,(p,r)=>new{Rank=r,Player=p});
var defensiveRank=球员名单。RankByDescending(p=>p.防守,(p,r)=>new{Rank=r,Player=p});
var onBallerRank=球员名单。RankByDescending(p=>p.防守,(p,r)=>new{Rank=r,Player=p});
var ruckRank=playerList.RankByDescending(p=>p.Ruck,(p,r)=>new{Rank=r,Player=p});
对于(int i=playerList.Count-1;i>=0;i--)
{
List<PlayerScore> playerList = new List<PlayerScore>();
foreach (var t in teams)
{
playerList.AddRange(t.TeamSelections.Where(x => x.DateInactive == null).OrderBy(x => x.PlayerName).Select(p => new PlayerScore
{
TeamId = p.TeamID,
PlayerName = p.PlayerName,
Club = p.Club,
ClubAbbreviation = Helper.Stats.GetClubAbbreviation(p.Club),
TeamLeagueId = p.Team.LeagueId,
TeamSelection = p.TeamSelectionId
}));
}
private static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
{
return length == 1 ? list.Select(t => new[] {t}) : GetPermutations(list, length - 1).SelectMany(t => list.Where(o => !t.Contains(o)), (t1, t2) => t1.Concat(new[] {t2}));
}
public static List<PlayerScore> TeamOfTheWeek(List<PlayerScore> playerList)
{
// Remove the players who scored 0 accross the board.
playerList.RemoveAll(player => player.Forward + player.TallForward + player.Offensive + player.Defensive + player.OnBaller + player.Ruck == 0);
// Rank each player score within a position.
var forwardRank = playerList.RankByDescending(p => p.Forward, (p, r) => new {Rank = r, Player = p});
var tallForwardRank = playerList.RankByDescending(p => p.TallForward, (p, r) => new {Rank = r, Player = p});
var offensiveRank = playerList.RankByDescending(p => p.Offensive, (p, r) => new { Rank = r, Player = p });
var defensiveRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
var onBallerRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
var ruckRank = playerList.RankByDescending(p => p.Ruck, (p, r) => new { Rank = r, Player = p });
for (int i = playerList.Count - 1; i >= 0; i--)
{
//var rankName = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Player.PlayerName;
var fw = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var tf = tallForwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var off = offensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var def = defensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var ob = onBallerRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
var ruck = ruckRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
if (fw >= 6 && tf >= 6 && off >= 6 && def >= 6 && ob >= 6 && ruck >= 6)
{
// Player is outside top 6 for each position so remove, and reduce permutations.
playerList.RemoveAt(i);
}
}
// Now update the playerId as this is used to join back to the array later.
var playerId = 0;
foreach (var p in playerList.OrderBy(p => p.PlayerName))
{
p.Id = playerId;
playerId = playerId + 1;
}
// Create and fill the position scores.
List<int[]> positionScoreArray = new List<int[]>();
foreach (var player in playerList.OrderBy(p => p.PlayerName))
{
// Player scored more than 0 so add to the positionScoreArray.
int[] playerScores = { player.Forward, player.TallForward, player.Offensive, player.Defensive, player.OnBaller, player.Ruck };
positionScoreArray.Add(playerScores);
}
// Players remaining in list pulled into array, ready for processing.
string[] playerNameArray = playerList.OrderBy(x => x.PlayerName).Select(p => p.PlayerName).ToArray();
// Load up the actual position scores to use in Parallel.For processing.
for (int i = 0; i < playerNameArray.Length; i++)
{
for (int j = 0; j < positionScoreArray.Count; j++)
{
if (j == 0)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Forward;
}
if (j == 1)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.TallForward;
}
if (j == 2)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Offensive;
}
if (j == 3)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Defensive;
}
if (j == 4)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.OnBaller;
}
if (j == 5)
{
var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
if (player != null)
positionScoreArray[i][j] = player.Ruck;
}
}
}
Stopwatch parallelForEachStopWatch = new Stopwatch();
parallelForEachStopWatch.Start();
var count = 0;
var playerIds = Enumerable.Range(0, playerNameArray.Length).ToList();
var best = new { PlayerIds = new List<int>(), TeamScore = 0 };
var positions = new[] { "FW", "TF", "Off", "Def", "OB", "Ruck" };
// Thread safe the Parallel.ForEach
lock (ThreadSafeObject)
{
Parallel.ForEach(GetPermutations(playerIds, positions.Length), perm =>
{
var teamScore = 0;
var players = perm.ToList();
for (int i = 0; i < positions.Length; i++) teamScore += positionScoreArray[players[i]][i];
if (teamScore > best.TeamScore) best = new {PlayerIds = players, TeamScore = teamScore};
if (count++%100000 == 0) Debug.WriteLine($"{count - 1:n0}");
}
);
}
parallelForEachStopWatch.Stop();
TimeSpan parallelForEach = parallelForEachStopWatch.Elapsed;
Debug.WriteLine($"Parallel.ForEach (secs): {parallelForEach.Seconds}");
Debug.WriteLine($"Permutations: {count:n0}");
Debug.WriteLine($"Team Score: {best.TeamScore}");
// Track Parallel.ForEach result.
var tcTotwRequest = new TelemetryClient();
tcTotwRequest.TrackEvent($"Permutations: {count:n0} Score: {best.TeamScore} Time (sec): {parallelForEach.Seconds}");
lock (ThreadSafeObject)
{
if (best.PlayerIds.Count > 0)
{
for (int i = 0; i < positions.Length; i++)
{
// Update the playerList, marking best players with TeamOfTheWeek position.
var player = playerList.FirstOrDefault(p => p.Id == best.PlayerIds[i]);
if (player != null)
{
player.TeamOfTheWeekPosition = positions[i];
player.TeamOfTheWeekScore = best.TeamScore;
}
}
}
}
return playerList.OrderBy(p => p.PlayerName).ToList();
}
}