パンデジタル数とは?C++でパンデジタル数を判定する方法を解説
パンデジタル数(Pandigital Number)とは
パンデジタル数とは、数学において、ある基数(base)で表したとき、その基数で使用されるすべての数字が有効数字の中に少なくとも1回ずつ現れる整数のことです。
たとえば10進法の場合、0から9までの各数字をすべて含む整数がパンデジタル数となります。「1023456789」や、0〜9をちょうど1回ずつ使った「3816547290」などがその代表例です。
さらに、0をまったく含まずに、1から基数−1までの各数字がすべて現れるゼロレスパンデジタル数(zeroless pandigital number)と呼ばれる種類も存在します。
この問題を解くためのアプローチ
- 数値と基数を入力として受け取ります。
- 基数が2未満または10より大きい場合は1を返して終了し、そうでなければ数値がパンデジタルかどうかを判定します。
- 整数型関数
is_pandigital(long long n, int base)が、数値と基数を引数として受け取ります。 - 数値に含まれるすべての数字の出現回数をカウントしていきます。
- すべての数字を走査し、出現回数が0の数字が1つでもあればfalseを返します。
- 整数型関数
is_zeroless_pandigital(long long n, int base)が、数値と基数を受け取り、0を含まないパンデジタル数かどうかを判定します。処理中に0が出現した時点で0を返します。 - すべての数字を走査し、出現回数が0の数字が見つかれば0を返します。
- 最後に、関数
check_number(long long number, int base)が数値と基数を受け取り、その数値が指定された基数において有効かどうかを検証します。有効であれば1、そうでなければ0を返します。
C++による実装例
#include <iostream>
#include <cstring>
using namespace std;
int is_pandigital(long long number, int base);
int is_zeroless_pandigital(long long number, int base);
int check_number(long long number, int base);
int main(){
long long number;
int base;
cout << "Enter a number: ";
cin >> number;
cout << "Enter base(min:2 to max-10): ";
cin >> base;
if(base < 2 || base > 10){
return 1;
}
if(check_number(number, base)){
if(is_pandigital(number, base)){
cout << number << " is a pandigital number in base " << base << endl;
}else{
cout << number << " is not a pandigital number in base " << base << endl;
}
if(is_zeroless_pandigital(number, base)){
cout << number << " is a zeroless pandigital number in base " << base << endl;
}else{
cout << number << " is not a zeroless pandigital number in base " << base << endl;
}
}else{
cout << number << " is not a valid number in base " << base << endl;
}
return 0;
}
/* 各数字の出現回数を格納する配列を用意 */
int is_pandigital(long long number, int base){
int digits[10], i;
memset(digits, 0, sizeof(int)*10);
/* 数値の各桁について出現回数を1ずつ加算 */
while(number > 0){
int digit = number % 10;
++digits[digit];
number /= 10;
}
/* すべての数字を走査し、出現回数0のものがあればfalseを返す */
for(i = 0; i < base; ++i)
if(digits[i] == 0)
return 0;
/* 出現回数0の数字が見つからなければtrueを返す */
return 1;
}
int is_zeroless_pandigital(long long number, int base){
int digits[10], i;
memset(digits, 0, sizeof(int)*10);
/* 各桁の出現回数を加算(0が出現したら即座にfalse) */
while(number > 0){
int digit = number % 10;
if(digit == 0) return 0;
++digits[digit];
number /= 10;
}
/* 1以降の数字を走査し、出現回数0のものがあればfalseを返す */
for(i = 1; i < base; ++i)
if(digits[i] == 0)
return 0;
/* 出現回数0の数字が見つからなければtrueを返す */
return 1;
}
/* 指定された基数において数値が有効かどうかをチェックする */
int check_number(long long number, int base){
while(number > 0){
int digit = number % 10;
if(digit > base - 1) return 0;
number /= 10;
}
return 1;
}
出力結果
上記のコードを実行すると、たとえば次のような出力が得られます。
Enter a number: 45 Enter base(min:2 to max-10):10 45 is not a pandigital number in base 10 45 is not a zeroless pandigital number in base 10
この例では、入力された「45」は10進法として有効な数値ですが、0〜9のすべての数字を含んでいないため、パンデジタル数でもゼロレスパンデジタル数でもないと判定されています。このように、各数字の出現回数を配列で管理して走査するだけで、シンプルにパンデジタル数の判定が実装できます。
-
C++で文字列の部分文字列の総数を求める方法を解説
この記事では、与えられた文字列から作成できる空でない部分文字列の個数を求める方法について解説します。入力 : string = "moon" 出力 : 10 説明 : 部分文字列は m、o、o、n、mo、oo、on、moo、oon、moon の 10 個です。 入力 : string = "yellow" 出力 : 21解法のアプローチ文字列の長さを n とします。上の例からも分かるように、考えられるすべての部分文字列の個数を求めるには、長さ n、(n-1)、(n-2)、(n-3)、……2、1 の部分文字列の個数を順に加算していく必要があります。部分文
-
C++で列車の停車駅の組み合わせ数を求める方法
地点XとYの間にはn個の中間駅があるとします。ここで、「どの2つの停車駅も隣り合わない」という条件のもとで、s個の駅に停車する列車の配置方法が何通りあるかを求める問題を考えてみましょう。この記事では、停車駅の組み合わせ数を求めるためのアプローチを段階的に詳しく解説します。この問題は、本質的には組合せ論の問題であり、s個の停車駅の選び方の総数を求めることになります。 問題を解くアプローチ まず具体例として、中間駅が8個あり、そのうち3個の駅に停車させたい場合を考えてみます。 n = 8, s = 3 このとき、列車が停車できない駅は(n − s)、つまり5個残ることになります。 停車できない