トップページに戻る    次のC#のサンプルへ    前のC#のサンプルへ

8-3 ぶどうの房パズル初級編

問題

下の図に1〜3までの自然数を1つずつ入れるパズルです。
下の段にある○の中には、すぐ上にある2つの○の中にある数字の差が入ります。
同じ数字は1回しか使えません。


正解例はこうなります


以上をふまえて、下の図での1〜6までの自然数の組み合わせを求めます。


ソース

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

class Program
{
    const int husaCnt = 6;

    struct JyoutaiDef
    {
        internal int Level;
        internal int[] IntArr;
    }

    static void Main()
    {
        var stk = new Stack<JyoutaiDef>();

        JyoutaiDef WillPush;
        WillPush.Level = 1;

        for (int I = 1; I <= husaCnt; I++) {
            WillPush.IntArr = new int[husaCnt];
            WillPush.IntArr[0] = I;
            stk.Push(WillPush);
        }

        while (stk.Count > 0) {
            JyoutaiDef Popped = stk.Pop();

            if (Popped.Level == husaCnt) {
                string WillOut = "";
                foreach (int each in Popped.IntArr) {
                    WillOut += each.ToString() + ",";
                }
                Console.WriteLine("Answer={0}", WillOut);
                continue;
            }

            WillPush.Level = Popped.Level + 1;

            for (int I = 1; I <= husaCnt; I++) {
                if (Popped.IntArr.Any(X => X == I)) continue;

                WillPush.IntArr = (int[])Popped.IntArr.Clone();
                WillPush.IntArr[WillPush.Level - 1] = I;

                if (IsValid(WillPush)) {
                    stk.Push(WillPush);
                }
            }
        }
    }

    static bool IsValid(JyoutaiDef pJyoutai)
    {
        int[] wkArrP = pJyoutai.IntArr;

        if (wkArrP[3] != 0 && wkArrP[0] != 0 && wkArrP[1] != 0) {
            if (wkArrP[3] != Math.Abs(wkArrP[0] - wkArrP[1])) return false;
        }
        if (wkArrP[4] != 0 && wkArrP[1] != 0 && wkArrP[2] != 0) {
            if (wkArrP[4] != Math.Abs(wkArrP[1] - wkArrP[2])) return false;
        }
        if (wkArrP[5] != 0 && wkArrP[3] != 0 && wkArrP[4] != 0) {
            if (wkArrP[5] != Math.Abs(wkArrP[3] - wkArrP[4])) return false;
        }
        return true;
    }
}


実行結果

Answer=6,2,5,4,3,1,
Answer=6,1,4,5,3,2,
Answer=5,6,2,1,4,3,
Answer=5,2,6,3,4,1,
Answer=4,6,1,2,5,3,
Answer=4,1,6,3,5,2,
Answer=2,6,5,4,1,3,
Answer=1,6,4,5,2,3,


解説

LINQのAny拡張メソッドを使ってみましたが、
LINQのContains拡張メソッドを使うか、
Array.IndexOfジェネリックメソッドを使うほうが良さそうだと後で気付きました・・・
MSDN --- Array.IndexOf(T) メソッド