これは、剰余算術を使用して簡単に実行できるはずです。
更新 2: (約束された正しいアルゴリズム)
public void ListMatches(List<string> ListTeam)
{
if (ListTeam.Count % 2 != 0)
{
ListTeam.Add("Bye");
}
int numDays = (numTeams - 1);
int halfSize = numTeams / 2;
List<string> teams = new List<string>();
teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());
int teamsSize = teams.Count;
for (int day = 0; day < numDays; day++)
{
Console.WriteLine("Day {0}", (day + 1));
int teamIdx = day % teamsSize;
Console.WriteLine("{0} vs {1}", teams[teamIdx], ListTeam[0]);
for (int idx = 1; idx < halfSize; idx++)
{
int firstTeam = (day + idx) % teamsSize;
int secondTeam = (day + teamsSize - idx) % teamsSize;
Console.WriteLine("{0} vs {1}", teams[firstTeam], teams[secondTeam]);
}
}
}
毎日のチームの試合を出力します。
アルゴリズムがどのように機能するかを簡単に説明してみましょう。
最初のチームを除くすべてのチームをローテーションしているので、最初のチームを除くすべてのチームを配列に入れると、その日に基づくインデックスオフセットを使用してその配列から最初のチームを読み取るだけでよいことに気付きました。モジュラー演算を正しくラップアラウンドします。実際には、その配列を両方向に無限に繰り返すものとして扱い、ビューを徐々に右 (または左) にスライドさせます。
ただし、問題が 1 つあります。それは、これが正しく機能するために、チームを特定の方法で順序付けする必要があるという事実です。そうしないと、正しい回転が得られません。このため、一致する 2 番目のチームも非常に独特な方法で読み取る必要があります。
リストを準備する正しい方法は次のとおりです。
- 最初のチーム (Team#1) をリストに入れないでください。
- チームリストの後半を取り、リストの先頭に置きます。
- リストの前半を取り、それを逆にしてリストに入れます (ただし、Team#1 は除きます)。
さて、リストから読み取る正しい方法は次のとおりです。
- 毎日、見ている最初のインデックスを ずつ増やします
1
。
- その場所で最初に表示されるチームについては、そのチームを Team#1 と一致させます。
- リスト内の次のチーム (
(day + idx) % numDays
) については、通常、チーム数の半分から 1 を引いた数だけオフセットされたチームと一致させます (最初の試合は自分たちで処理したため、マイナス 1 です)。ただし、リストの後半は元に戻すことによって準備されているため、元に戻したリストの後半でそのオフセットを一致させる必要があります。より簡単な方法は、これがリストの最後から同じインデックスに一致することと同等であることを確認することです。day
である現在のオフセットが与えられ(day + (numDays - idx)) % numDays
ます。
更新 3:私のソリューションが複雑な選択、マッチング、配列要素の反転を含むことに満足していませんでした。自分の解決策に何が含まれるかを考えた後、与えられたチームの順序を維持することに夢中になっていることに気付きました。ただし、これは要件ではなく、最初の順序を気にしないことで、異なるが同等に有効なスケジュールを取得できます。重要なのは、説明の後半で説明する選択アルゴリズムだけです。
したがって、次の行を単純化できます。
teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());
に:
teams.AddRange(ListTeam); // Copy all the elements.
teams.RemoveAt(0); // To exclude the first team.