トップページに戻る    次の増井さんの書籍の問題へ    前の増井さんの書籍の問題へ

Q41 美しい?IPアドレス


C#のソース

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

class Program
{
    static void Main()
    {
        int[] KouhoNumArr = DeriveKouhoNumArr();
        int UB = KouhoNumArr.GetUpperBound(0);

        int AnswerCnt = 0;

        for (int I = 0; I <= UB; I++) {
            for (int J = 0; J <= UB; J++) {
                if (I == J) continue;
                int A = KouhoNumArr[I], B = KouhoNumArr[J];
                int C = DeriveRevBinNum(B), D = DeriveRevBinNum(A);

                var wkList = new List<int>();
                wkList.AddRange(DeriveEachNumArr(A));
                wkList.AddRange(DeriveEachNumArr(B));
                wkList.AddRange(DeriveEachNumArr(C));
                wkList.AddRange(DeriveEachNumArr(D));

                //数字の重複があったらNG
                if (wkList.Count > wkList.Distinct().Count()) continue;

                //0から9の、10個の数字がなかったらNG
                if (wkList.Count < 10) continue;

                AnswerCnt++;
                Console.WriteLine("解{0}を発見。{1,3}.{2,3}.{3,3}.{4,3}",
                    AnswerCnt, A, B, C, D);
            }
        }
    }

    //使用可能な10進数の配列を返す
    static int[] DeriveKouhoNumArr()
    {
        var WillReturn = new List<int>();
        for (int I = 0; I <= 255; I++) {
            int[] EachNumArr1 = DeriveEachNumArr(I);
            int RevBinNum = DeriveRevBinNum(I);
            //反転した数が255より大きかったらNG
            if (RevBinNum > 255) continue;

            //数字の重複があったらNG
            int[] EachNumArr2 = DeriveEachNumArr(RevBinNum);
            int[] wkArr = EachNumArr1.Concat(EachNumArr2).ToArray();
            if (wkArr.Length > wkArr.Distinct().Count()) continue;

            WillReturn.Add(I);
        }
        return WillReturn.ToArray();
    }

    //数値の各数字の配列を返す
    static int[] DeriveEachNumArr(int pTarget)
    {
        var WillReturn = new List<int>();
        int CopiedVal = pTarget;
        do {
            int ModVal = CopiedVal % 10;
            WillReturn.Add(ModVal);
            CopiedVal /= 10;
        } while (CopiedVal > 0);
        return WillReturn.ToArray();
    }

    //10進数を引数とし、2進数にして反転し、10進数に変換した数値を返す
    static int DeriveRevBinNum(int pTarget)
    {
        string BinStr = Convert.ToString(pTarget, 2).PadLeft(8, '0');
        string RevBinStr = new string(BinStr.Reverse().ToArray());
        return Convert.ToInt32(RevBinStr, 2);
    }
}


実行結果

解1を発見。 34.179.205. 68
解2を発見。 34.205.179. 68
解3を発見。 68.179.205. 34
解4を発見。 68.205.179. 34
解5を発見。179. 34. 68.205
解6を発見。179. 68. 34.205
解7を発見。205. 34. 68.179
解8を発見。205. 68. 34.179


解説

最初に使用可能な10進数を求めて、
候補となる組み合わせを減らしてます。