Created
May 10, 2014 16:52
-
-
Save paralleltree/986da20312f423f7ec08 to your computer and use it in GitHub Desktop.
場合の数
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
namespace Test | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
foreach (var item in Combination(new string[] { "A", "B", "C", "D" }, 2)) | |
{ | |
Console.WriteLine(string.Join(", ", item)); | |
} | |
Console.WriteLine(); | |
foreach (var item in Combination(new string[] { "A", "B", "C", "D" }, 4)) | |
{ | |
Console.WriteLine(string.Join(", ", item)); | |
} | |
Console.WriteLine(); | |
foreach (var item in Permutation(new string[] { "A", "B", "C", "D" }, 2)) | |
{ | |
Console.WriteLine(string.Join(", ", item)); | |
} | |
Console.WriteLine(); | |
foreach (var item in Permutation(new string[] { "A", "B", "C" })) | |
{ | |
Console.WriteLine(string.Join(", ", item)); | |
} | |
Console.ReadKey(); | |
} | |
/* | |
static IEnumerable<IEnumerable<T>> Permutation<T>(IEnumerable<T> source) | |
{ | |
// 要素が一つだけならそのまま返す | |
if (source.Count() > 1 == false) return new List<IEnumerable<T>>() { source }; | |
// 結果を格納するList | |
var result = new List<List<T>>(); | |
// 先頭に1要素ずつ置く | |
foreach (var item in source) | |
{ | |
// 先頭以外の要素で組み合わせを求める | |
foreach (var inner in Combination(source.TakeWhile(p => !p.Equals(item)).Concat(source.SkipWhile(p => !p.Equals(item)).Skip(1)))) | |
{ | |
// 1つの組み合わせを表すList | |
var each = new List<T>(); | |
// 先頭の要素を入れる | |
each.Add(item); | |
// 後続の組み合わせをそのまま入れる | |
foreach (T inneritem in inner) each.Add(inneritem); | |
// 組み合わせ1つ出来上がり | |
result.Add(each); | |
} | |
} | |
return result; | |
} | |
*/ | |
static IEnumerable<IEnumerable<T>> Permutation<T>(IEnumerable<T> source) | |
{ | |
return Permutation(source, source.Count()); | |
} | |
/// <summary> | |
/// 順列を求める | |
/// </summary> | |
static IEnumerable<IEnumerable<T>> Permutation<T>(IEnumerable<T> source, int count) | |
{ | |
// パラメータチェック | |
if (source.Count() < count || count < 0) throw new ArgumentOutOfRangeException("count", "取り出す個数が不正です。"); | |
// 要素が一つだけならそのまま返す | |
if (source.Count() > 1 == false) return new List<IEnumerable<T>>() { source }; | |
// 結果を格納するList | |
var result = new List<List<T>>(); | |
// 先頭に1要素ずつ置く | |
foreach (var item in source) | |
{ | |
// 最後の要素だったら返す | |
if (count > 1 == false) | |
{ | |
result.Add(new List<T>() { item }); | |
continue; | |
} | |
// 先頭以外の要素で組み合わせを求める | |
foreach (var inner in Permutation(source.TakeWhile(p => !p.Equals(item)).Concat(source.SkipWhile(p => !p.Equals(item)).Skip(1)), count - 1)) | |
{ | |
// 1つの組み合わせを表すList | |
var each = new List<T>(); | |
// 先頭の要素を入れる | |
each.Add(item); | |
// 後続の組み合わせをそのまま入れる | |
foreach (T inneritem in inner) each.Add(inneritem); | |
// 組み合わせ1つ出来上がり | |
result.Add(each); | |
} | |
} | |
return result; | |
} | |
/// <summary> | |
/// 組み合わせを求める | |
/// </summary> | |
static IEnumerable<IEnumerable<T>> Combination<T>(IEnumerable<T> source, int count) | |
{ | |
// 典型的な場当たりコーディング | |
// パラメータチェック | |
if (source.Count() < count || count < 0) throw new ArgumentOutOfRangeException("count", "取り出す個数が不正です。"); | |
// 要素が一つだけならそのまま返す | |
if (source.Count() > 1 == false) return new List<IEnumerable<T>>() { source }; | |
// 結果を格納するList | |
var result = new List<List<T>>(); | |
// 残りの組み合わせに使うリスト | |
var remain = new List<T>(source); | |
// 先頭に1要素ずつ置く | |
foreach (var item in source) | |
{ | |
// 最後の要素だったら飛ばす | |
if (count > 1 == false) | |
{ | |
result.Add(new List<T>() { item }); | |
continue; | |
} | |
remain.Remove(item); | |
// 組み合わせる要素がなくなったら終わり | |
if (remain.Count > 0 == false || remain.Count < count - 1) break; // ←特にこ↑こ↓ | |
// 先頭以外の要素で組み合わせを求める | |
foreach (var inner in Combination(remain, count - 1)) | |
{ | |
// 1つの組み合わせを表すList | |
var each = new List<T>(); | |
// 先頭の要素を入れる | |
each.Add(item); | |
// 後続の組み合わせをそのまま入れる | |
foreach (T inneritem in inner) each.Add(inneritem); | |
// 組み合わせ1つ出来上がり | |
result.Add(each); | |
} | |
} | |
return result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment