12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#で順列と組み合わせを求める

Last updated at Posted at 2017-06-09

Project Euler を解いていたら、すごい勢いで使うので作りました。

順列 (Permutation)

例えば [ 1, 2, 3 ] から以下のような結果が欲しい。※ P(n=3, k=3)で6通り

[ [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1] ]

こんなメソッドを用意する

シーケンス(IEnumerable<T>)の拡張メソッドとして定義してみます。

public static IEnumerable<IEnumerable<T>> Perm<T>(this IEnumerable<T> items, int? k = null)
{
	if (k == null)
		k = items.Count();

	if (k == 0)
	{
		yield return Enumerable.Empty<T>();
	}
	else
	{
		var i = 0;
		foreach (var x in items)
		{
			var xs = items.Where((_, index) => i != index);
			foreach (var c in Perm(xs, k - 1))
				yield return c.Before(x);

			i++;
		}
	}
}

// 要素をシーケンスに追加するユーティリティ
public static IEnumerable<T> Before<T>(this IEnumerable<T> items, T first)
{
	yield return first;

	foreach (var i in items)
		yield return i;
}

こんな風に使う

// P(n=3, k=3)の例
var source = new int[] { 1, 2, 3 };
var perm = source.Perm();
var result = perm.Select(x => x.ToArray()).ToArray();
// result => [ [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1] ]

引数kに順列の項数を与えることができます。(省略すると元のシーケンスと同じ項数になる)

// P(n=3, k=2)の例
var source = new int[] { 1, 2, 3 };
var perm = source.Perm(2); // k = 2
var result = perm.Select(x => x.ToArray()).ToArray();
// result => [ [1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2] ]

組み合わせ (Combination)

例えば [ 1, 2, 3 ] から項数2の組み合わせを求める場合、以下のような結果が欲しい。※ C(n=3, r=2)で3通り

[ [1, 2], [1, 3], [2, 3] ]

こんなメソッドを用意する

順列と大体同じです。
組み合わせの場合は既に列挙した要素を含めてはいけないので、Skip(i)で列挙済み要素を飛ばします。

public static IEnumerable<IEnumerable<T>> Comb<T>(this IEnumerable<T> items, int r)
{
	if (r == 0)
	{
		yield return Enumerable.Empty<T>();
	}
	else
	{
		var i = 1;
		foreach (var x in items)
		{
			var xs = items.Skip(i);
			foreach (var c in Comb(xs, r - 1))
				yield return c.Before(x);

			i++;
		}
	}

}

こんな風に使う

// C(n=3, r=2)の例
var source = new int[] { 1, 2, 3 };
var comb = source.Comb(2);
var result = comb.Select(x => x.ToArray()).ToArray();
// result => [ [1, 2], [1, 3], [2, 3] ]
12
15
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?