C++で電話番号が「ファンシーナンバー」かどうかを判定する方法
10桁の携帯電話番号が与えられたとき、その番号が「ファンシーナンバー(覚えやすい特別な番号)」であるかどうかを判定するのが本記事の目的です。ファンシーナンバーには以下の3つの条件があり、少なくとも1つでも満たしていれば、その番号はファンシーナンバーとみなされます。
- 同じ数字が3回連続して現れる:例えば「555」など
- 3つの連続する数字が昇順または降順に並んでいる:例えば「123」「321」など
- 同じ数字が4回以上現れる:例えば「8965499259」では「9」が4回出現しています
例として挙げる「9859009976」は、「9」が4回出現しているため3つ目の条件を満たしており、ファンシーナンバーであると言えます。
アプローチのポイント
電話番号は数値ではなく文字列として扱います。文字列として扱うことで、先頭が「0」で始まる番号も問題なく処理でき、各桁へのアクセスも簡単になります。
特に3つ目の条件(同じ数字が4回以上出現する)を判定する際には、各数字(0〜9)の出現回数を記録する必要があります。ここでは長さ10の整数配列を頻度表として使用し、ハッシュの基本的な考え方を応用します。
C++での実装例
#include <iostream>
using namespace std;
// 条件1:同じ数字が3回連続して現れるかを判定
bool consecutiveThreeSameDigits(string s) {
for (int i = 0; i < s.size() - 2; i++) {
if (s[i] == s[i + 1] && s[i + 1] == s[i + 2])
return true;
}
return false;
}
// 条件2:3つの連続する数字が昇順または降順かを判定
bool incDecThree(string s) {
for (int i = 0; i < s.size() - 2; i++) {
if ((s[i] < s[i + 1] && s[i + 1] < s[i + 2]) ||
(s[i] > s[i + 1] && s[i + 1] > s[i + 2]))
return true;
}
return false;
}
// 条件3:同じ数字が4回以上現れるかを判定(ハッシュの考え方を使用)
bool fourOccurrence(string s) {
int freq[10] = {0}; // 各数字(0〜9)の出現回数
for (int i = 0; i < s.size(); i++)
freq[s[i] - '0']++;
for (int i = 0; i < 10; i++)
if (freq[i] >= 4)
return true;
return false;
}
// ファンシーナンバーかどうかを総合的に判定
bool isFancyNumber(string s) {
if (consecutiveThreeSameDigits(s) || incDecThree(s) || fourOccurrence(s))
return true;
else
return false;
}
int main() {
string s = "7609438921";
if (isFancyNumber(s))
cout << "This is fancy number";
else
cout << "This is not a fancy number";
}
コードの解説
consecutiveThreeSameDigits関数
文字列を先頭から順に走査し、隣り合う3桁がすべて同じ数字であればtrueを返します。ループ範囲は「サイズ − 2」までなので、配列外参照を防ぎながら安全に比較できます。
incDecThree関数
隣り合う3桁が昇順(s[i] < s[i+1] < s[i+2])または降順(s[i] > s[i+1] > s[i+2])のどちらかに該当すればtrueを返します。「123」のような階段状の並びや「321」のような逆階段状の並びを検出できます。
fourOccurrence関数
長さ10の頻度配列freqを用意し、各桁の文字から'0'を引くことで対応するインデックスの出現回数をカウントします。これは最も基本的なハッシュ(直接アドレス法)の活用例です。0〜9のすべての数字について出現回数を確認し、4回以上のものがあればtrueを返します。
isFancyNumber関数
上記の3つの判定関数を呼び出し、論理和(||)で結合しています。いずれか1つでもtrueを返せば、その番号はファンシーナンバーと判定されます。
実行結果
This is fancy number
サンプルの入力「7609438921」では、先頭の「7・6・0」が降順に並んでいるため、2つ目の条件を満たし、ファンシーナンバーと判定されます。
計算量
- 時間計算量:O(n)(nは桁数。今回は固定の10桁なので実質O(1))
- 空間計算量:O(1)(サイズ10の固定長頻度配列のみを使用)
このように、シンプルな線形走査と頻度カウントを組み合わせるだけで、3つの条件を効率よく判定できます。番号の桁数が変わっても、同じロジックをそのまま流用できる点がこの実装の利点です。
-
C++でNが五角数(ペンタゴナル数)かどうかを判定するプログラム
五角数とはある整数 N が与えられたとき、それが五角数(ペンタゴナル数)であるかどうかを判定するのが本記事の目的です。五角数とは、点を並べることで正五角形の形を描くことができる数のことです。これらの数は、五角形を構成する頂点や点として表現できます。五角数の例としては、次のような数列が挙げられます。1, 5, 12, 22, 35, 51, 70, 92 …五角数を判定する公式ある数が五角数かどうかは、以下の公式を利用して確認できます。p(n) = (3 × n² − n) / 2ここで、n は五角形を構成する点の個数を表します。この式から得られる値が順に 1, 5, 12, 22, 35… と
-
アームストロング数を判定するC++プログラムの書き方と解説
アームストロング数とはアームストロング数(Armstrong Number)とは、各桁の数字を「総桁数」乗した値の合計が、元の数そのものと等しくなる数のことです。例えば、153は3桁の数なので、各桁を3乗して足し合わせると元の数に戻ります。主なアームストロング数の例は以下の通りです。3 = 3^1 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153 371 = 3^3 + 7^3 + 1^3 = 27 + 343 + 1 = 371 407 = 4^3 + 0^3 + 7^3 = 64 + 0 + 343 = 407この性質を利用すると、任意の整数がアームスト