2017年04月02日

TypeScriptでProject Euler #17 「数字の文字数」

   このエントリーをはてなブックマークに追加 Clip to Evernote

問題

1 から 5 までの数字を英単語で書けば one, two, three, four, five であり, 全部で 3 + 3 + 5 + 4 + 4 = 19 の文字が使われている.

では 1 から 1000 (one thousand) までの数字をすべて英単語で書けば, 全部で何文字になるか.

注: 空白文字やハイフンを数えないこと. 例えば, 342 (three hundred and forty-two) は 23 文字, 115 (one hundred and fifteen) は20文字と数える. なお, "and" を使用するのは英国の慣習.

   Project Euler日本語翻訳サイト から引用

TypeScriptのコード

単にアルファベットの数を足していっても良かったのですが、文字列を組み立て、最後に長さを求めたほうが直感的だったので、これを採用しました。 かなり泥臭いコードになってしまいましたが、1000までならば、あっというまに答えが求まるので良しとします。

import * as Utils from './utils';

class Solver {
    exec(maxnum: number): number {
        return Utils.makeSeq(1, maxnum)
                    .map(x => this.numToString(x).length)
                    .reduce( (x,y) => x + y);           
    }

    numToString(num: number): string {
        if (num < 100) {
            return this.numToStringUnder100(num);
        }
        if (num < 1000) {
            var s = "";
            s += this.numbers[Math.floor(num / 100)] + this.numbers[100];
            if (num % 100 != 0) {
                s = s + "and" + this.numToStringUnder100(num % 100);
            }
            return s;
        }
        return this.numbers[1000];
    }

    numToStringUnder100(num: number): string {
        if (num < 20)
            return this.numbers[num];
        if (num % 10 === 0)
            return this.numbers[num];
        else
            return this.numbers[Math.floor(num / 10) * 10] + this.numbers[num % 10];
    }

    numbers: { [key: number]: string } = {
        1: "one", 2: "two", 3: "three", 4: "four", 5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine", 10: "ten",
        11: "eleven", 12: "twelve", 13: "thirteen", 14: "fourteen",
        15: "fifteen", 16: "sixteen", 17: "seventeen", 18: "eighteen", 19: "nineteen",
        20: "twenty", 30: "thirty", 40: "forty", 50: "fifty", 60: "sixty", 70: "seventy", 80: "eighty", 90: "ninety",
        100: "hundred", 1000: "onethousand"
    };

}

class Application {
    static run(): void {
        let sw = Utils.Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(1000);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        } 
    }
}

Application.run();

makeSeqで、1から1000までの配列を作り、mapでそれぞれの文字列を組み立てその長さを配列にし、reduceで合計を求めています。


※Stopwatchクラスについては、「TypeScriptでProject Euler #0」 を見てください。



 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52488916