Pythonで電話番号を整形(リフォーマット)するプログラムの実装方法
ここでは、数字・スペース・ハイフン(-)で構成された電話番号の文字列を受け取り、決められたルールに従って読みやすい形式へ整形するプログラムをPythonで実装します。
整形のルール
- 文字列に含まれるすべてのスペースとハイフンを除去する
- 残った数字を左から順に3桁ずつのブロックにグループ化し、残りが4桁以下になったら終了する
- 最後に残った数字は、その桁数に応じて次のようにグループ化する
- 2桁の場合:長さ2のブロック1つ
- 3桁の場合:長さ3のブロック1つ
- 4桁の場合:長さ2のブロック2つ(例:12-34)
こうして作られた各ブロックはハイフンで連結され、最終的な電話番号となります。
入出力の例
たとえば、入力が s = "9-6-84102-4 7-8" の場合、出力は 968-410-24-78 になります。
アルゴリズムの考え方
- 結果を格納する
digitsと、現在処理中のブロックを保持するblkを空文字列として初期化します。 - 入力文字列
sの各文字iについて以下を繰り返します。iが数字ならblkに連結するblkの長さが3になったら、blkとハイフンをdigitsに追加し、blkを空に戻す
- ループ終了後、
blkに残っている桁数で分岐します。- 0桁の場合:末尾の余分なハイフンを除いた
digitsをそのまま返す - 1桁の場合:直前の3桁ブロックから1桁を後ろに移動させ、「2桁+2桁」の形に組み替えて返す(4桁を2-2に分割するルールを満たすため)
- 2桁の場合:
digitsにblkをそのまま連結して返す
- 0桁の場合:末尾の余分なハイフンを除いた
Pythonでの実装例
以下が実際のコードです。
def solve(s):
digits = ""
blk = ""
for i in s:
if i.isnumeric():
blk += i
if len(blk) == 3:
digits += blk+"-"
blk = ""
if len(blk) == 0:
return digits[:-1]
elif len(blk) == 1:
return digits[:-2]+"-"+digits[-2]+blk
elif len(blk) == 2:
return digits+blk
s = "9-6-84102-4 7-8"
print(solve(s))入力
"9-6-84102-4 7-8"
出力
968-410-24-78
ポイントの解説
このアルゴリズムの肝は、残り1桁の場合の処理です。単純に3桁区切りで進めると、最後に1桁だけ余ってしまうことがあります。そこで、直前に作った3桁ブロックの末尾1桁を後ろに移動し、「2桁+2桁」の2ブロックに再構成することで、4桁の分割ルールに自然に対応できます。計算量は文字列の長さをNとするとO(N)で、非常に効率的な実装となっています。
-
Pythonで二分探索木(BST)の指定範囲内にあるノード数を求める方法
問題の概要 二分探索木(BST)が与えられ、さらに左側の境界値 l と右側の境界値 r が指定されます。このとき、木に含まれるすべてのノードの中で、値が l 以上 r 以下の範囲内にあるノードの個数を求めるのが目的です。 例えば、次のような木が与えられたとします。 このとき l = 7、r = 13 とすると、範囲内に含まれるノードは 8、10、12 の3つなので、出力は 3 になります。 アルゴリズムの考え方 スタックを使った反復的な深さ優先探索(DFS)で木をたどります。重要なポイントは、二分探索木の性質を活かして枝刈り(pruning)を行うことです。値が境界より小さいノードの左側の
-
Pythonで解く!電話番号からすべての文字の組み合わせを生成する方法
2〜9までの数字を含む文字列が与えられたとき、その番号が表しうるすべての文字の組み合わせを返すことを考えます。以下は、電話のダイヤルボタンと同じように、各数字に割り当てられた文字のマッピングです。なお、「1」はどの文字にも対応しない点に注意してください。 12a b c3d e f4g h i5j k l6m n o7p q r s8t u v9w x y z*0# たとえば、入力として「23」が与えられた場合、生成される可能性のある文字列は次のようになります。 [ad, ae, af, bd, be, bf, cd, ce, cf] 解法のアプローチ この問題は、再帰的なバックトラッキングを