Project Euler 17

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

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

注: 空白文字やハイフンを数えないこと。例えば、342 (three hundred and forty-two) は 23 文字、115 (one hundred and fifteen) は20文字と数える。なお、"and" を使用するのは英国の慣習。
NtoS[i_] :=
  Which[
   i == 1000, "onethousand",

   (* 100の倍数のとき *)   
   i >= 100 && IntegerQ[i/100] == True,
   {NtoS[(i - Mod[i, 100])/100] <> "hundred"},
   
   (* 100以上で、100の倍数でないとき *)
   i >= 100 && IntegerQ[i/100] == False,
   {NtoS[(i - Mod[i, 100])/100] <> "hundredand" <> NtoS[Mod[i, 100]]},
   
   (* 20以上で、10の倍数のとき *)
   i >= 20 && IntegerQ[i/10] == True,
   {NtoS2[i]},
   
   (* 20以上で、10の倍数でないとき *)
   i >= 20 && IntegerQ[i/10] == False,
   {NtoS2[i - Mod[i, 10]] <> NtoS[Mod[i, 10]]},
   
   i == 1, "one",
   i == 2, "two",
   i == 3, "three",
   i == 4, "four",
   i == 5, "five",
   i == 6, "six",
   i == 7, "seven",
   i == 8, "eight",
   i == 9, "nine",
   i == 10, "ten",
   i == 11, "eleven",
   i == 12, "twelve",
   i == 13, "thirteen",
   i == 14, "fourteen",
   i == 15, "fifteen",
   i == 16, "sixteen",
   i == 17, "seventeen",
   i == 18, "eighteen",
   i == 19, "nineteen",
   i == 0, ""
   ];

NtoS2[i_] := Switch[i,
   20, "twenty",
   30, "thirty",
   40, "forty",
   50, "fifty",
   60, "sixty",
   70, "seventy",
   80, "eighty",
   90, "ninety"];

Total[Flatten[Table[StringLength[NtoS[i]], {i, 1000}]]]

数字を英単語列にしてくれるような関数はMathematicaでもさすがにないので、普通に関数を作りました。
「 <> 」は、Mathematicaでの文字列の連結です。

C/C++

#include <iostream>
#include <string>

using namespace std;

string NumbertoString2dig(int n){
	switch(n){
		case 20: return "twenty"; break;
		case 30: return "thirty"; break;
		case 40: return "forty"; break;
		case 50: return "fifty"; break;
		case 60: return "sixty"; break;
		case 70: return "seventy"; break;
		case 80: return "eighty"; break;
		case 90: return "ninety"; break;
	}
	return "";
}

string NumbertoString(int n){
	if(n == 1000) return "onethousand";

	// 100の倍数のとき
	else if( n%100 == 0) return NumbertoString(n/100)+"hundred";

	// 100以上で100の倍数でないとき
	else if( n>100 ) return NumbertoString(n/100)+"hundredand"+NumbertoString(n%100);

	// 20以上で10の倍数のとき
	else if( n>=20 && n%10==0 ) return NumbertoString2dig(n);

	// 20以上で10の倍数でないとき
	else if( n>=20) return NumbertoString2dig(n-n%10)+NumbertoString(n%10);

	else{
		switch(n){
			case 1: return "one"; break;
			case 2: return "two"; break;
			case 3: return "three"; break;
			case 4: return "four"; break;
			case 5: return "five"; break;
			case 6: return "six"; break;
			case 7: return "seven"; break;
			case 8: return "eight"; break;
			case 9: return "nine"; break;
			case 10: return "ten"; break;
			case 11: return "eleven"; break;
			case 12: return "twelve"; break;
			case 13: return "thirteen"; break;
			case 14: return "fourteen"; break;
			case 15: return "fifteen"; break;
			case 16: return "sixteen"; break;
			case 17: return "seventeen"; break;
			case 18: return "eighteen"; break;
			case 19: return "nineteen"; break;
			case 0: return ""; break;
		}
	}
	return "";
}

int main(){
	string str;
	int sum=0;

	for(int i=1 ; i<=1000 ; i++){
		str = NumbertoString(i);
		sum += str.length();
	}
	cout << sum << endl;

	int end;
	cin >> end;
	return 0;
}

クラスを作ろうと思ったんだけど、どんなクラスを作ればいいかよくわからなかったので、結局愚直に関数。