Project Euler で紹介されている問題42を解いてみました。単語を数字に変換して、条件をみたすか判断していきます。すでに紹介した問題22と似たようなプログラムとなります。
Project Euler 問題42(三角数単語)
三角数の n 番目の項は、tn = n(n+1)/2 で与えられます。最初の 10 項は、以下となります。
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …
単語の各文字をそのアルファベット位置に対応する数字に変換し、これらの値を加算することで、単語の値を求めます。例えば、SKY の単語の値は 19 + 11 + 25 = 55 = t10 となります。単語の値が三角数である場合、その単語を三角数単語と呼びます。
words.txt(右クリックして保存できます)は、約 2000 の一般的な英単語を含む 16K のテキスト ファイルです。このファイルに含まれる三角数単語の個数を求めよ。
考察
問題が提供しているファイル「p042_words.txt」の内容は、以下のようになっています。
"A","ABILITY","ABLE","ABOUT","ABOVE","ABSENCE","ABSOLUTELY", ...
テキストファイルに1786個の英単語が含まれていました。
以下の方針で解答を求めます。
- ダブルクォーテーションやカンマを取り除いて単語だけを取得する。
- 単語の綴りから単語の値を求める。
- 単語の値が三角数か判定する。三角数なら解答に1を加える。
- 最後に解答を出力する。
解答例
単語の値を求める関数 calc_score は、問題22から流用しました。ただし、引数の名前を変更しました。
三角数か判定するために、配列 is_triangle_number をあらかじめ計算しておきます(28から40行目)。あらかじめ計算しておく上限は、マクロ定数 TRIANGLE_NUMBER_MAX で定めます。この値は 10000 としました(21行目)。三角数か判定する配列の要素数が足りない場合は、警告を出力しています(62から64行目)。
標準入力から単語を切り出し、単語の値を求めて三角数か判定しました。最終的に C++ のプログラムは、以下となりました。
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
using namespace std;
int calc_score(string word)
{
int index = 0;
int score = 0;
while (word[index] != 0) {
score += (word[index] - 'A' + 1);
++index;
}
return score;
}
#define TRIANGLE_NUMBER_MAX 10000
int main()
{
string buffer;
cin >> buffer; // Read all file.
vector<bool> is_triangle_number(TRIANGLE_NUMBER_MAX, false);
int i = 1;
int j = 2;
is_triangle_number[1] = 1;
while (1) {
i += j;
++j;
if (i < TRIANGLE_NUMBER_MAX) {
is_triangle_number[i] = true;
} else {
break;
}
}
vector<string> words;
string word_buffer;
bool in_word = false;
for (size_t i = 0; i < buffer.size(); ++i) {
if (isalpha(buffer[i])) {
word_buffer += buffer[i];
in_word = true;
} else {
if (in_word) {
words.push_back(word_buffer);
word_buffer.clear();
in_word = false;
}
}
}
cout << "number of words :" << words.size() << endl;
int answer = 0;
for (auto word : words) {
int score = calc_score(word);
if (score >= TRIANGLE_NUMBER_MAX) {
cout << "Program needs more triangle number table!" << endl;
}
if (is_triangle_number[score]) {
++answer;
}
}
cout << "Problem042: " << answer << endl;
return 0;
}
プログラムを動かすと、三角数のバッファの数が10000で足りることも分かりました。
最後に
問題に従い、確実にプログラムすれば解ける問題でした。過去に作った関数も再利用することができました。
引き続き、Project Euler の問題を紹介していきます。