ようこそ。睡眠不足なプログラマのチラ裏です。

LINQで順列生成

元ネタ:順列 - 一生酩酊


id:taguoさんが、文字列の順列をC#のLINQで生成していらっしゃいました。
おお、こいつはカッコイイぜ!! とても勉強になりました。


しかし、"abbc"のように同一の文字を含む文字列については順列が生成されませんでした。
あまりLINQ慣れしていないので無駄等あるやもしれませんが、
元ネタコードを改造して同一文字を含む場合も順列生成できるように対応してみました。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    static class Program
    {
        static void Main(string[] args)
        {
            GetPermutation("abbc").ToList().ForEach(s => Console.WriteLine(s));
            Console.ReadLine();
        }

        static IEnumerable<string> GetPermutation(string str)
        {
            return Enumerable.Range(0, str.Length).Select(_ => str.ToCharArray())
                   .Aggregate(new[] { "" }.AsEnumerable()
                              , (a, ca) => from s in a
                                           from c in ca
                                           select s + c.ToString()
                              ).Distinct()
                               .Where(x => { if (x == str) return true;
                                             return x.Sort() == str.Sort(); });
        }

        static string Sort(this string self)
        {
            var tmp = self.ToCharArray().ToList();
            tmp.Sort();
            string ret = null;
            tmp.ForEach(x => { ret += x.ToString(); });
            return ret;
        }
    }
}


実行結果

abbc
abcb
acbb
babc
bacb
bbac
bbca
bcab
bcba
cabb
cbab
cbba


パフォーマンス的にどーよ?というのは、元ネタ同様度外視の方向で・・・(;´・ω・`)
しかし、なにか煮え切らない。もっとカッコイイ書き方がありそうな気がする。。


(追記:2008/08/06)

元ネタ:順列 - 一生酩酊で、id:tagouさんからお返事をいただきました。
新たにLINQで順列生成(ジェネリクス対応)するエレガントなコードを書いてくださいました。
どうもありがとうございます。私含めLINQ初心者にはとても勉強になると思われるので、
気になる方は是非チェックしましょう。