【C#】Project Euler 11,12,13問目

#はじめに
C#を用いてProjectEulerに挑戦している人の記録です。VisualStudio2017で、1つのフォームアプリの中に問題番号のボタンを作成し、そのボタンをクリックすると結果をラベルに表示するという形式でやっています。
#11問目
次の数字の表の、上下左右斜めのいずれかの方向で連続する4つの数字の積のうち最大のものを求めよ

```csharp
 private void button11_Click(object sender, EventArgs e)
        {           
            int[,] NumberString;
            NumberString = new int[20, 20] {
       { 08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91, 08},
       { 49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 04, 56, 62, 00},
       { 81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 03, 49, 13, 36, 65},
       { 52, 70, 95, 23, 04, 60, 11, 42, 69, 24, 68, 56, 01, 32, 56, 71, 37, 02, 36, 91},
       { 22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80},
       { 24, 47, 32, 60, 99, 03, 45, 02, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50},
       { 32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70},
       { 67, 26, 20, 68, 02, 62, 12, 20, 95, 63, 94, 39, 63, 08, 40, 91, 66, 49, 94, 21},
       { 24, 55, 58, 05, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72},
       { 21, 36, 23, 09, 75, 00, 76, 44, 20, 45, 35, 14, 00, 61, 33, 97, 34, 31, 33, 95},
       { 78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 03, 80, 04, 62, 16, 14, 09, 53, 56, 92},
       { 16, 39, 05, 42, 96, 35, 31, 47, 55, 58, 88, 24, 00, 17, 54, 24, 36, 29, 85, 57},
       { 86, 56, 00, 48, 35, 71, 89, 07, 05, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58},
       { 19, 80, 81, 68, 05, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 04, 89, 55, 40},
       { 04, 52, 08, 83, 97, 35, 99, 16, 07, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66},
       { 88, 36, 68, 87, 57, 62, 20, 72, 03, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69},
       { 04, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 08, 46, 29, 32, 40, 62, 76, 36},
       { 20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 04, 36, 16},
       { 20, 73, 35, 29, 78, 31, 90, 01, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 05, 54},
       { 01, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 01, 89, 19, 67, 48}
            };
            int Vertical = 0;
            int Horizontal = 0;
            int RightDiagonal = 0;
            int LeftDiagonal = 0;
            int MaxValue = 0;
             for (int i = 0; i <= NumberString.GetUpperBound(0); i++)
            {
                for (int j = 0; j <= NumberString.GetUpperBound(1); j++)
                {
                    if (i + 3 <= NumberString.GetUpperBound(0)) { 
                        Vertical = NumberString[i, j] * NumberString[i + 1, j] * NumberString[i + 2, j] * NumberString[i + 3, j];
                    }
                    if (j + 3 <= NumberString.GetUpperBound(1))
                    {
                        Horizontal = NumberString[i, j] * NumberString[i, j + 1] * NumberString[i, j + 2] * NumberString[i, j + 3];
                    }
                    if (i + 3 <= NumberString.GetUpperBound(0) && j + 3 <= NumberString.GetUpperBound(1))
                    {
                        RightDiagonal = NumberString[i, j] * NumberString[i + 1, j + 1] * NumberString[i + 2, j + 2] * NumberString[i + 3, j + 3];
                    }
                    if (i < 17 && j > 2)
                    {
                        LeftDiagonal = NumberString[i, j] * NumberString[i + 1, j - 1] * NumberString[i + 2, j - 2] * NumberString[i + 3, j - 3];
                    }
                    int Max = Max4(Vertical, Horizontal, RightDiagonal, LeftDiagonal);
                    if (MaxValue < Max) MaxValue = Max;
                }
            }
            label1.Text = "Answer = " + MaxValue;
        }

 public static int Max4(int a, int b, int c, int d)
        {
            int Max = a;
            Max = Math.Max(Max, b);
            Max = Math.Max(Max, c);
            Max = Math.Max(Max, d);
            return Max;
        }
```
表を2次元配列で宣言し、インデックスを操作することで上下左右斜めの数字4つを取り出し、積を計算して最大値を計算しています。／のような方向に進む時のインデックス操作は考える必要がありました。素直に条件判定を繰り返したので効率が悪そうです。
#12問目
三角数とは、1からその番目の数までを足したものである。例：7番目の三角数：1+2+3+4+5+6+7=28
三角数の7番目までの数列：1, 3, 6, 10, 15, 21, 28
500個より多く約数をもつ最初の三角数を求めよ

```CSharp
       private void button12_Click(object sender, EventArgs e)
        {
            int TriangularNumber = 0;
            int i = 1;
            while (true)
            {
                int Exp = 0;
                TriangularNumber += i;
                int Number = TriangularNumber;
                int NumberOfPrime = 1;

                for (int j = 2; Number >= j; j++)
                {
                    while (Number % j == 0)
                    {
                        Number /= j;
                        Exp++;
                    }
                    NumberOfPrime *= (1 + Exp);
                    Exp = 0;
                }
                if (NumberOfPrime > 500) { break; }
                i++;
            }
            label1.Text = "Answer = " + TriangularNumber;
        }
```
三角数を計算し、その数を2から順に割っていき、割り切れる数の個数を計算し、（1も約数なので1を足している）、500個よりも多かったら無限ループを抜けるという方法でやりました。
#13問目
50桁の数字100個の合計の上から10桁(この数字は問題には書いてあるが、あまりにも巨大なため内容をデスクトップのa.txtから読み込んでいる）

```CSharp
 private void button13_Click(object sender, EventArgs e)
        {
 string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\a.txt";
            Encoding utf8 = Encoding.GetEncoding("utf-8");
            string[] NumberString;
            NumberString = new string[100];

            using (var reader = new StreamReader(path, utf8))
            {
                try
                {
                    for (int i = 0; i < 100; i++)
                    {
                        NumberString[i] = reader.ReadLine();
                    }
                }
                catch (Exception ex)
                {

                }
            }
            long Number = 0;
            long digit = 0;

            for (int Div = 40; Div >= 0; Div -= 10)
            {
                Number = digit;
                for (int i = 0; i < 100; i++)
                {
                    Number += long.Parse(NumberString[i].Substring(Div, 10));
                }
                if (Div != 0)
                {
                    digit = Number / (long)Math.Pow(10, 10);
                }
                else
                {
                    string Answer = Number.ToString();
                    label1.Text = "Answer = " + Answer.Substring(0, 10);
                }
            }
        }
```
100個の数字の桁の末尾から10個ずつ（41～50桁目、31～40桁目、21～30桁目、11～20桁目、1～10桁目）取り出し、それぞれの桁目ごとの合計を出し、繰上りを足しながら最上位まで行き、上から10桁を取り出すという方法でやりました。