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

Cマガ電脳クラブ(第002回) ガンコ素数をさがせ!

問題

7193という数は素数であり、しかも右側からひとつずつ削っていっても、719, 71, 7 のようにすべて素数になる。
これを左ガンコ素数と呼ぶことにする。

6823 はそれ自身が素数であり、左から順に削った 823, 23, 3 が全部素数になる。これは右ガンコ素数だ。
さて問題。「左ガンコ素数であり、同時に右ガンコ素数である」最大の素数を見つけていただきたい。


ソース

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

class Program
{
    const int Jyougen = 9999999;
    static int[] SosuuArr = new int[Jyougen + 1];

    //エラトステネスの篩
    static void Eratosthenes()
    {
        for (int I = 2; I <= SosuuArr.GetUpperBound(0); I++) {
            SosuuArr[I] = I;
        }
        for (int I = 2; I * I <= SosuuArr.GetUpperBound(0); I++) {
            if (I != 2 && I % 2 == 0) continue;

            if (SosuuArr[I] != 0) {
                for (int J = I * 2; J <= SosuuArr.GetUpperBound(0); J += I) {
                    SosuuArr[J] = 0;
                }
            }
        }

        SosuuArr = SosuuArr.Where(X => X != 0).ToArray();
    }

    static int[] DeriveStartArr()
    {
        var wkList = new List<int>(SosuuArr);

        //右端が1は、対象外
        wkList.RemoveAll(X => X % 10 == 1);

        //2桁以上で右端が9は、対象外
        wkList.RemoveAll(X => X >= 10 && X % 10 == 9);

        //2桁以上で左端が1,4,6,8,9は、対象外
        wkList.RemoveAll(X =>
        {
            string wkStr = X.ToString();
            return X >= 10 && (
                wkStr.StartsWith("1") || wkStr.StartsWith("4") || wkStr.StartsWith("6") ||
                wkStr.StartsWith("8") || wkStr.StartsWith("9"));
        });

        //0を含むと対象外
        wkList.RemoveAll(X => X.ToString().Contains('0'));

        return wkList.ToArray();
    }

    static void Main()
    {
        Console.WriteLine("{0}以下のガンコ素数を列挙します。", Jyougen);

        Eratosthenes();
        int[] StartArr = DeriveStartArr();

        foreach (var AnyInt in SosuuArr) {
            //1桁はガンコ素数
            if (AnyInt < 10) {
                Console.WriteLine("{0}はガンコ素数", AnyInt);
                continue;
            }

            bool IsOK = true;
            for (int I = 1; I <= DeriveKetasuu(AnyInt) - 1; I++) {
                int WK1 = AnyInt % CalcBekijyou(I);
                int WK2 = AnyInt / CalcBekijyou(I);

                if (Array.BinarySearch<int>(SosuuArr, WK1) < 0 ||
                    Array.BinarySearch<int>(SosuuArr, WK2) < 0) {
                    IsOK = false;
                    break;
                }
            }
            if (IsOK) Console.WriteLine("{0}はガンコ素数", AnyInt);
        }
    }

    static int DeriveKetasuu(int pTarget)
    {
        if (pTarget < 10) return 1;
        if (pTarget < 100) return 2;
        if (pTarget < 1000) return 3;
        if (pTarget < 10000) return 4;
        if (pTarget < 100000) return 5;
        if (pTarget < 1000000) return 6;
        return 7;
    }

    static int CalcBekijyou(int pJyousuu)
    {
        int WillReturn = 1;
        for (int I = 1; I <= pJyousuu; I++) {
            WillReturn *= 10;
        }
        return WillReturn;
    }
}


実行結果

9999999以下のガンコ素数を列挙します。
2はガンコ素数
3はガンコ素数
5はガンコ素数
7はガンコ素数
23はガンコ素数
37はガンコ素数
53はガンコ素数
73はガンコ素数
313はガンコ素数
317はガンコ素数
373はガンコ素数
797はガンコ素数
3137はガンコ素数
3797はガンコ素数
739397はガンコ素数


解説

9999999以下のガンコ素数を列挙して、最大のガンコ素数が
 739397でしたので、最大の素数を見つけるという題意を満たしてます。

Problem37 切り詰めても素数になる数の総和