Project Euler

Project Euler 問題41(パンデジタル素数)を解いてみる

760x428_Euler_041

Project Euler で紹介されている問題41を解いてみました。パンデジタルな最大の素数を求めます。ライブラリで順列を使える C++ を利用して解きました。

Project Euler 問題41(パンデジタル素数)

1 から n までのすべての数字を 1 回だけ使用する n 桁の数字は、パンデジタルであると呼びます。例えば、2143 は 4 桁のパンデジタル数であり、素数でもあります。

最大となる n 桁のパンデジタル素数を求めてください。

考察

パンデジタル数については、問題32問題38でも取り扱いました。パンデジタル数は、0 を含む場合もあるようです。Wikipedeia の「パンデジタル数」の定義では、0 を含めています。この問題では、Project Euler の流儀に従います。

3桁のパンデジタル数は、各桁の数を加えると 1 + 2 + 3 = 6 となります。各桁の和が3で割れる数は、3の倍数となるため、素数にはなりません。他の場合も確認してみます。

  • 2桁の場合、1 + 2 = 3 となるため、3の倍数となる。
  • 3桁の場合、1 + 2 + 3 = 6 となるため、3の倍数となる。
  • 5桁の場合、1 + 2 + … + 5 = 15 となるため、3の倍数となる。
  • 6桁の場合、1 + 2 + … + 6 = 21 となるため、3の倍数となる。
  • 8桁の場合、1 + 2 + … + 8 = 36 となるため、3の倍数となる。
  • 9桁の場合、1 + 2 + … + 9 = 45 となるため、3の倍数となる。

パンデジタルな数が素数になるためには、4桁か7桁であることが必要なことが分かりました。7桁の場合を調べれば、最大のパンデジタル素数を求めることができそうです。

解答例

C では標準ライブラリで順列のサポートがありません。標準ライブラリで順列のサポートがあるC++を使って解きます。

最大値を求めるため、ひとつ前の順列を生成する prev_permutataion を使います(38行目)。考察で確認したように 7 桁の場合を計算します。

素数であるか判定する is_Prime は、道具箱から流用しました。

以下は、C++ のプログラムです。

#include <iostream>
#include <algorithm>

using namespace std;

int is_prime(int n)
{
	int answer = 1;
	int i;

	if (n <= 1) {
		answer = 0;
	}
	for (i = 2; i * i <= n; ++i) {
		if (n % i == 0) {
			answer = 0;
			break;
		}
	}

	return answer;
}

int main(void)
{
	int n[7] = {7, 6, 5, 4, 3, 2, 1};

	int answer = -1;
	do {
		int num = 0;
		for (int i = 0; i < 7; ++i) {
			num = num * 10 + n[i];
		}
		if (is_prime(num)) {
			answer = num;
			break;
		}
	} while (prev_permutation(n, n + 7));

	printf("Problem041: %d\n", answer);

	return 0;
}

7桁のパンデジタル素数が見つかり、このプログラムの出力が正解と判定されました。

最後に

パンデジタル素数は、4桁か7桁になるため、7桁の場合を調べて正解を求めることができました。

引き続き、Project Euler の問題を紹介していきます。

COMMENT

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

CAPTCHA