Project Euler

Project Euler 問題42(三角数単語)を解いてみる

760x428_Euler_042

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. ダブルクォーテーションやカンマを取り除いて単語だけを取得する。
  2. 単語の綴りから単語の値を求める。
  3. 単語の値が三角数か判定する。三角数なら解答に1を加える。
  4. 最後に解答を出力する。

解答例

単語の値を求める関数 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 の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA