C++
 Computer >> コンピューター >  >> プログラミング >> C++

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つの条件を効率よく判定できます。番号の桁数が変わっても、同じロジックをそのまま流用できる点がこの実装の利点です。

  1. C++でNが五角数(ペンタゴナル数)かどうかを判定するプログラム

    五角数とはある整数 N が与えられたとき、それが五角数(ペンタゴナル数)であるかどうかを判定するのが本記事の目的です。五角数とは、点を並べることで正五角形の形を描くことができる数のことです。これらの数は、五角形を構成する頂点や点として表現できます。五角数の例としては、次のような数列が挙げられます。1, 5, 12, 22, 35, 51, 70, 92 …五角数を判定する公式ある数が五角数かどうかは、以下の公式を利用して確認できます。p(n) = (3 × n² − n) / 2ここで、n は五角形を構成する点の個数を表します。この式から得られる値が順に 1, 5, 12, 22, 35… と

  2. アームストロング数を判定する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この性質を利用すると、任意の整数がアームスト