【C#】Project Euler 20,21,22問目

#はじめに
C#を用いてProjectEulerに挑戦している人の記録です。VisualStudio2017で、1つのフォームアプリの中に問題番号のボタンを作成し、そのボタンをクリックすると結果をラベルに表示するという形式でやっています。
#20問目
100!の各位の数字の和を求めよ

```Csharp
private void button20_Click(object sender, EventArgs e)
        {
            BigInteger Number = 1;
            for (int i = 1; i < 100; i++)
            {
                Number *= i;
            }
            string NumberString = Number.ToString();
            int SumEachNumber = 0;
            for (int i = 0; i < NumberString.Length; i++)
            {
                char EachNumber = NumberString[i];
                SumEachNumber += (EachNumber - '0');
            }
            label1.Text = "Answer = " + SumEachNumber;
        }
```
1. 100の階乗をBigIntegerに格納
1. 文字列に変換
2. 一文字ずつintに変換して足す
という手順で行いました。

#21問目
d(n) を n の真の約数の和と定義する. (真の約数とは n 以外の約数のことである. )
もし, d(a) = b かつ d(b) = a (a ≠ b のとき) を満たすとき, a と b は友愛数(親和数)であるという.

例えば, 220 の約数は 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 なので d(220) = 284 である.
また, 284 の約数は 1, 2, 4, 71, 142 なので d(284) = 220 である.

それでは10000未満の友愛数の和を求めよ.

```Csharp
private void button21_Click(object sender, EventArgs e)
        {
            int Number = 0;
            List<int> DivSumList = new List<int>();
            DivSumList.Add(0);
            int DivSum = 0;
            int AmicableSum = 0;


            for (Number = 1; Number < 10001; Number++)
            {
                for (int i = 2; i < Number; i++)
                {
                    if (Number % i == 0)
                    {
                        DivSum += i;
                    }
                }
                DivSumList.Add(DivSum + 1);
                DivSum = 0;
            }
            for (int i = 0; i < 10001; i++)
            {
                if (DivSumList[i] < 10001)
                {
                    if (i == DivSumList[DivSumList[i]] && i != DivSumList[i])
                    {
                        textBox1.AppendText(i + " " + DivSumList[i] + " ");
                        AmicableSum += i + DivSumList[i];
                    }
                }
            }
            label1.Text = "Answer = " + AmicableSum / 2;//同じ組を2回数えてしまうため2で割る
        }
```
1. 10001までの数字の約数の和をリストに格納
2. 友愛数の定義に従って友愛数の組を求める  
-下から順番に数えるため、同じ組をもう一度数えてしまう。2で割る  
-デバッグのため、友愛数の組をテキストボックスに表示
という手順で行いました。

#22問目
5000個以上の名前が書かれている46Kのテキストファイル names.txt を用いる. まずアルファベット順にソートせよ.

のち, 各名前についてアルファベットに値を割り振り, リスト中の出現順の数と掛け合わせることで, 名前のスコアを計算する.

たとえば, リストがアルファベット順にソートされているとすると, COLINはリストの938番目にある. またCOLINは 3 + 15 + 12 + 9 + 14 = 53 という値を持つ. よってCOLINは 938 × 53 = 49714 というスコアを持つ.

ファイル中の全名前のスコアの合計を求めよ.

```CSharp
private void button22_Click(object sender, EventArgs e)
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\names.txt";
            Encoding utf8 = Encoding.GetEncoding("utf-8");
            string Name = "";
            using (var Reader = new StreamReader(path, utf8))
            {
                try
                {
                    Name = Reader.ReadToEnd();
                }
                catch (Exception ex)
                {

                }
            }
            char[] DelimiterChars = { ',' };
            string[] Names = Name.Split(DelimiterChars);
            int i = 1;
            int ScoreSum = 0;
            foreach (string EachName in Names.OrderBy(n => n))
            {
                int Score = EachName.ToCharArray().Where(x => x >= 'A').Select(x => x - 'A' + 1).Sum() * i;
                ScoreSum += Score;
                i++;
            }
            label1.Text = "answer = " + ScoreSum;
        }
```
1. デスクトップにあるnames.txtの内容を読み取る
2. 文字列を,で分けて1つずつの名前を取り出す
3. スコアの計算
という手順で行いました。

#感想
今回は素直に計算して解くことができました。22問目ではラムダ式を初めて使いました。少し理解が足りていないので、使いこなせるまで理解します。