【C#】ProjectEuler32, 33, 34問目

#はじめに
C#を用いてProjectEulerに挑戦している人の記録です。VisualStudio2017で、1つのフォームアプリの中に問題番号のボタンを作成し、そのボタンをクリックすると結果をラベルに表示するという形式でやっています。
#32問目
すべての桁に 1 から n が一度だけ使われている数をn桁の数がパンデジタル (pandigital) であるということにしよう: 例えば5桁の数 15234 は1から5のパンデジタルである.

7254 は面白い性質を持っている. 39 × 186 = 7254 と書け, 掛けられる数, 掛ける数, 積が1から9のパンデジタルとなる.

掛けられる数/掛ける数/積が1から9のパンデジタルとなるような積の総和を求めよ.

HINT: いくつかの積は, 1通り以上の掛けられる数/掛ける数/積の組み合わせを持つが1回だけ数え上げよ.

```CSharp
private void button32_Click(object sender, EventArgs e)
        {
            var NumberSumHash = new HashSet<int>();
            for (int i = 1; i < 10000; i++)
            {
                for (int j = 1; j < 10000; j++)
                {
                    int Number = i * j;
                    if (Number > 9999) break;
                    string NumberString = Number.ToString() + i.ToString() + j.ToString();
                    var NumberList = new List<char>(NumberString);
                    if (NumberList.Count == 9 && NumberList.Contains('0') == false)
                    {
                        var Hash = new HashSet<char>(NumberList);
                        if (Hash.Count == 9)
                        {
                            NumberSumHash.Add(Number);
                            textBox1.AppendText("i=" + i + " j=" + j + "Number=" + Number + "  ");
                        }
                    }
                }
            }
            int NumberSum = NumberSumHash.Sum();
            label1.Text = "Answer = " + NumberSum;
        }
```
10000以下の数字の掛けられる数・かける数の積をリストにして0以外で9桁あることを確認した後、ハッシュリストにして9桁あった結果を合計したものを答えとしました。
#33問目
49/98は面白い分数である.「分子と分母からそれぞれ9を取り除くと, 49/98 = 4/8 となり, 簡単な形にすることができる」と経験の浅い数学者が誤って思い込んでしまうかもしれないからである. (方法は正しくないが，49/98の場合にはたまたま正しい約分になってしまう．)

我々は 30/50 = 3/5 のようなタイプは自明な例だとする.

このような分数のうち, 1より小さく分子・分母がともに2桁の数になるような自明でないものは, 4個ある.

その4個の分数の積が約分された形で与えられたとき, 分母の値を答えよ.

```CSharp
 public static int[] Normal(int Numer, int Denom)
        {
            for (int i = 2; i < 20; i++)
            {
                while (Denom % i == 0 && Numer % i == 0)
                {
                    Numer /= i;
                    Denom /= i;
                }
            }
            int[] Number = new int[2];
            Number[0] = Numer;
            Number[1] = Denom;
            return Number;
        }
 private void button33_Click(object sender, EventArgs e)
        {
            var FindList = new List<int>();
            var NormalList = new int[2];
            var StringNormalList = new int[2];
            for (int Denom = 20; Denom < 100; Denom++)
            {
                for (int Numer = 12; Numer < Denom; Numer++)
                {
                    if (Denom % 10 == 0) continue;
                    if (Denom % 11 == 0) continue;

                    string NumerString = Numer.ToString();
                    string DenomString = Denom.ToString();
                    if (NumerString[1] == DenomString[0])
                    {
                        int CalcNumer = Numer;
                        int CalcDenom = Denom;
                        NumerString = NumerString.Remove(1, 1);
                        DenomString = DenomString.Remove(0, 1);
                        StringNormalList = Normal(int.Parse(NumerString), int.Parse(DenomString));
                        NumerString = StringNormalList[0].ToString();
                        DenomString = StringNormalList[1].ToString();
                        //文字列の部分も約分する必要がある

                        NormalList = Normal(CalcNumer, CalcDenom);
                        if (NumerString == NormalList[0].ToString() && DenomString == NormalList[1].ToString())
                        {
                            textBox1.AppendText("That is" + Numer + "/" + Denom + "  ");
                            FindList.Add(Numer);
                            FindList.Add(Denom);
                        }
                    }
                }
            }
            int AnswerNumer = 1;
            int AnswerDenom = 1;
            for (int i = 0; i < FindList.Count; i = i + 2)
            {
                AnswerNumer *= FindList[i];
                AnswerDenom *= FindList[i + 1];
            }
            NormalList = Normal(AnswerNumer, AnswerDenom);
            label1.Text = "Answer = " + NormalList[1];
        }
```
Normalという関数で約分を実装してます。間違った約分をした後、正しい約分と比べて等しかった分数の積を約分して答えを出しています。
#34問目
145は面白い数である. 1! + 4! + 5! = 1 + 24 + 120 = 145となる.

各桁の数の階乗の和が自分自身と一致するような数の和を求めよ.

注: 1! = 1 と 2! = 2 は総和に含めてはならない.

```CSharp
 public static int fact(int Number)
        {
            int CalcNumber = 1;
            for (int i = Number; i > 1; i--)
            {
                CalcNumber *= i;
            }
            return CalcNumber;
        }
 private void button34_Click(object sender, EventArgs e)
        {
            int[] Number = new int[8];
            var AnswerList = new List<int>();
            foreach (int a in Number)
            {
                Number[a] = 0;
            }
            for (int i = 3; i < 2540161; i++)
            {
                string NumberString = i.ToString();
                int Sum = 0;
                for (int j = 0; j < NumberString.Length; j++)
                {
                    Number[j] = NumberString[j] - '0';
                    Sum += fact(Number[j]);
                }
                if (i == Sum)
                {
                    AnswerList.Add(i);
                    textBox1.AppendText(i + " ");
                }
            }
            label1.Text = AnswerList.Sum().ToString();
        }
```
factという関数で階乗を実装してます。9!が362880で、最大値は7桁だと362880*7=2540160、8桁だと362880*8=2903040であり、8桁以降は題意を満たす数字にならないため、for文は7桁の最大値まで回すことにしています。数字を文字列に変換し、一文字ずつint型に変換してその数の階乗を合計しています。