読者です 読者をやめる 読者になる 読者になる

Project Euler : Problem 17 『Number letter counts』

C# プログラミング 算数

Whitby AbbeyWhitby Abbey / archangel 12
projecteuler.net


問題

 1から1000まで(1000含む)の数字を英語表記したとき、総文字数はいくらか?


注:one(3文字), two(3文字), …, one hundred(10文字), one hundred and one(16文字), …, one thousand


め・ん・ど・く・さぁーい!

 正直めんどくさい。
まず、1から19までの単品(one - nineteen)
次に、20からの10区切り(twenty - ninety)
んで最後に100(hundred)と1000(thousand)
何に時間かかったかって、この文字と文字数を調べるのに時間かかった。
「二度としたくない作業」リストに追加しておきたい。


 本題とは関係ないけど、なぜ20未満まで1単語表記なんだろうか。
20進数だったとか?
それとも12まで特徴あるから12進数だったんだろうか?


とりあえず文字を作ってカウントしてみる

 最初から数字-文字数のテーブルを作ってしまえばいいんだけど、
ちゃんと文字ができてるか気になったので、文字バージョンを先に作った。
そうすると何かifが入り組んてわちゃわちゃしたコードに……正直見にくい。


(文字版)コード
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Problem17
{
    class Program
    {
        static Dictionary<int, string> Number = new Dictionary<int, string>();

        static void Main(string[] args)
        {
            Debug.WriteLine(Result());
        }

        /// <summary>
        /// 必要な文字を入れておく。1000は別。
        /// </summary>
        static void Init()
        {
            Number[1] = "one";
            Number[2] = "two";
            Number[3] = "three";
            Number[4] = "four";
            Number[5] = "five";
            Number[6] = "six";
            Number[7] = "seven";
            Number[8] = "eight";
            Number[9] = "nine";
            Number[10] = "ten";
            Number[11] = "eleven";
            Number[12] = "twelve";
            Number[13] = "thirteen";
            Number[14] = "fourteen";
            Number[15] = "fifteen";
            Number[16] = "sixteen";
            Number[17] = "seventeen";
            Number[18] = "eighteen";
            Number[19] = "nineteen";
            Number[20] = "twenty";
            Number[30] = "thirty";
            Number[40] = "forty";
            Number[50] = "fifty";
            Number[60] = "sixty";
            Number[70] = "seventy";
            Number[80] = "eighty";
            Number[90] = "ninety";
            Number[100] = "hundred";
        }

        static int Result()
        {
            Init();

            return LetterCount();
        }

        static int LetterCount()
        {
            int sum = 0;

            for (int i = 1; i < 1000; i++)
            {
                String str = "";
                int n = i;

                if (i >= 100)
                {
                    str += HunderdNumber(i / 100);
                    n = int.Parse(i.ToString().Substring(1));
                }

                str += Under2Digit(n, i);

                sum += str.Length;
            }

            sum += "onethousand".Length;

            return sum;
        }

        /// <summary>
        /// 100の位
        /// </summary>
        static String HunderdNumber(int n)
        {
            return Number[n] + Number[100];
        }

        static String Under2Digit(int n, int i)
        {
            String s = "";

            if (i >= 100 & n != 0) s += "and";

            if (n >= 20)
            {
                int tmp = (n / 10) * 10;

                if (n - tmp != 0) return s + Number[tmp] + Number[n - tmp];
                else return s + Number[tmp];
            }
            else if (n >= 1)
            {
                return s + Number[n];
            }
            else
            {
                return "";
            }
        }
    }
}
もうちょっと考えてみる

 ifが入り組んでるのをもうちょっと何とかしたいなと思って書き換えた。
変更点1 : 数字をそれぞれの桁で表現することにした
変更点2 : 文字を作らず文字数をカウントするだけにした
変更点3 : ifらへんを整理した


コード2
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Problem17_2
{
    class Program
    {
        static Dictionary<int, int> Number = new Dictionary<int, int>();

        static void Main(string[] args)
        {
            Init();

            Debug.WriteLine(Result());
        }

        /// <summary>
        /// 必要な文字を入れておく。1000は別。
        /// </summary>
        static void Init()
        {
            Number[0] = 0;
            Number[1] = 3;// "one";
            Number[2] = 3;// "two";
            Number[3] = 5;// "three";
            Number[4] = 4;// "four";
            Number[5] = 4;// "five";
            Number[6] = 3;// "six";
            Number[7] = 5;// "seven";
            Number[8] = 5;// "eight";
            Number[9] = 4;// "nine";
            Number[10] = 3;// "ten";
            Number[11] = 6;// "eleven";
            Number[12] = 6;// "twelve";
            Number[13] = 8;// "thirteen";
            Number[14] = 8;// "fourteen";
            Number[15] = 7;// "fifteen";
            Number[16] = 7;// "sixteen";
            Number[17] = 9;// "seventeen";
            Number[18] = 8;// "eighteen";
            Number[19] = 8;// "nineteen";
            Number[20] = 6;// "twenty";
            Number[30] = 6;// "thirty";
            Number[40] = 5;// "forty";
            Number[50] = 5;// "fifty";
            Number[60] = 5;// "sixty";
            Number[70] = 7;// "seventy";
            Number[80] = 6;// "eighty";
            Number[90] = 6;// "ninety";
            Number[100] = 7;// "hundred";
        }

        static int Result()
        {
            int sum = 0;

            for (int a = 0; a < 10; a++)
            {
                for (int b = 0; b < 10; b++)
                {
                    for (int c = 0; c < 10; c++)
                    {
                        int n = b * 10 + c;

                        if(n <= 20)
                        {
                            sum += Number[n];
                        }
                        else
                        {
                            sum += Number[b * 10] + Number[c];
                        }

                        if(a >= 1)
                        {
                            sum += Number[a] + Number[100];
                        }

                        if(a >= 1 & n != 0)
                        {
                            sum += 3;
                        }
                    }
                }
            }

            return sum + 11;
        }
    }
}

 +3と+11はandとonethousandです。


答え

 21124



基礎からわかる数・数式と図形の英語―豊富な用語と用例

基礎からわかる数・数式と図形の英語―豊富な用語と用例

数量表現の英語トレーニングブック(CD BOOK)

数量表現の英語トレーニングブック(CD BOOK)

数の英語表現辞典

数の英語表現辞典