LINQで非決定性計算

Haskellやっぱ難しいよ。難しいって。 - テンポラリ
↑前にhaskellでやってたのをC# + LINQでやってみた。
前は意味わかんなかったけど、今なら読めるしかけるなぁ。

        public void f1()
        {
            var result =
                  from baker in Enumerable.Range(1, 5)
                  from cooper in Enumerable.Range(1, 5)
                  from fletcher in Enumerable.Range(1, 5)
                  from miller in Enumerable.Range(1, 5)
                  from smith in Enumerable.Range(1, 5)
                  where !new[] { baker, cooper, fletcher, miller, smith }.Dup()
                  && baker != 5
                  && cooper != 1
                  && fletcher != 1 && fletcher != 5
                  && miller > cooper
                  && Math.Abs(smith - fletcher) != 1
                  && Math.Abs(fletcher - cooper) != 1
                  select new { baker = baker, cooper = cooper, fletcher = fletcher, miller = miller, smith = smith };


            result.ToList().ForEach(
                r => Console.WriteLine(
                    "baker:{0} cooper:{1} fletcher:{2} miller:{3} smith:{4}",
                    r.baker,
                    r.cooper,
                    r.fletcher,
                    r.miller,
                    r.smith));
        }


ユーティリティがコレ


    public static class Util
    {
        public static bool Dup(this int[] values)
        {
            return values.Distinct().Count() != values.Length;
        }
    }


メソッドで書くとこんな感じ?


        public void f2()
        {
            var result =
                    Enumerable.Range(1, 5).SelectMany(
                        baker => Enumerable.Range(1, 5).SelectMany(
                        cooper => Enumerable.Range(1, 5).SelectMany(
                        fletcher => Enumerable.Range(1, 5).SelectMany(
                        miller => Enumerable.Range(1, 5).SelectMany(
                        smith => Enumerable.Repeat(new
                        {
                            baker = baker,
                            cooper = cooper,
                            fletcher = fletcher,
                            miller = miller,
                            smith = smith
                        }, 1)))))).Where(
                            r => !new[] { r.baker, r.cooper, r.fletcher, r.miller, r.smith }.Dup()
                                && r.baker != 5
                                && r.cooper != 1
                                && r.fletcher != 1
                                && r.fletcher != 5
                                && r.miller > r.cooper
                                && Math.Abs(r.smith - r.fletcher) != 1
                                && Math.Abs(r.fletcher - r.cooper) != 1);

            result.ToList().ForEach(
                r => Console.WriteLine(
                    "baker:{0} cooper:{1} fletcher:{2} miller:{3} smith:{4}",
                    r.baker,
                    r.cooper,
                    r.fletcher,
                    r.miller,
                    r.smith));
        }