Pythonでn(t)形式の文字列を展開・デコードするプログラムの実装方法
問題の概要
ある文字列 s が与えられ、これはより長い元の文字列をエンコードしたものだとします。n(t) という表記は「文字列 t を n 回繰り返して連結したもの」を意味し、t には通常の文字列だけでなく、別のエンコード済み文字列が再帰的に含まれることもあります。この記事では、エンコードされた文字列 s をデコード(展開)するPythonプログラムを紹介します。
たとえば、入力が s = "3(pi)2(3(am))0(f)1(u)" の場合、出力は "pipipiamamamamamamu" になります。「pi」が3回、「am」が6回(2×3)、「f」は0回のため無視され、「u」が1回繰り返された結果です。
解決アプローチ:再帰的なパース処理
この問題は、再帰下降パース(再帰的な構文解析)を使うことで効率的に解けます。全体の流れは次のとおりです。
- 読み取り位置を示すインデックス
iを 0 で初期化します。 - 文字列を解析する関数
parse()を定義します。 - 結果を一時的に保持するためのリスト
ansを用意します。 iが文字列の長さ未満で、かつs[i]が ")" ではない間、以下を繰り返します。- s[i] が数字の場合:
dを 0 で初期化し、s[i]が数字である限り「d = 10 × d + s[i] の整数値」で更新しながらiを進めます(これにより複数桁の回数にも対応できます)。iを 1 つ進めて "(" を読み飛ばします。segment = parse()を呼び出し、括弧の中身を再帰的に取得します。iを 1 つ進めて ")" を読み飛ばします。segmentをd回ansに追加します。
- それ以外の場合:
s[i]をansの末尾に追加し、iを 1 つ進めます。
- s[i] が数字の場合:
ansの要素を連結した文字列を返します。
メイン側からは parse() の戻り値をそのまま返すだけです。
実装例
理解を深めるために、実際のPythonコードを見てみましょう。
class Solution:
def solve(self, s):
i = 0
def parse():
nonlocal i
ans = []
while i < len(s) and s[i] != ")":
if s[i].isdigit():
# 数値部分を読み取る(複数桁対応)
d = 0
while s[i].isdigit():
d = 10 * d + int(s[i])
i += 1
i += 1 # "(" をスキップ
segment = parse()
i += 1 # ")" をスキップ
ans.extend(segment for _ in range(d))
else:
ans.append(s[i])
i += 1
return "".join(ans)
return parse()
ob = Solution()
s = "3(pi)2(3(am))0(f)1(u)"
print(ob.solve(s))
入力
"3(pi)2(3(am))0(f)1(u)"
出力
pipipiamamamamamamu
ポイントまとめ
- 入れ子になった
n(t)構造は、再帰呼び出しによって自然に処理できます。 - 回数
nは必ずしも1桁とは限らないため、連続する数字をまとめて読み取る処理が必要です。 n = 0の場合は該当部分が出力に現れず、空文字列として扱われます。- 計算量は出力文字列の長さにほぼ比例し、入力サイズに対して線形時間で動作します。
-
Pythonで16進数の文字列を10進数に変換する方法を解説
この記事では、16進数の文字列を10進数に変換する問題の解決策について詳しく解説します。課題の概要16進数形式の文字列が与えられたとき、それを対応する10進数の値に変換することを目標とします。例えば、16進数の「F」は10進数では「15」に相当します。この問題には主に2つのアプローチがあります。力ずく(ブルートフォース)な手法:int関数を使った明示的な型変換組み込みモジュールを活用する手法:astモジュールのliteral_eval関数を使用方法1:int関数を使った変換最もシンプルで一般的な方法は、Pythonの組み込み関数であるint()を利用するものです。この関数は2つの引数を受け取り
-
Python 3で辞書を使って文字列をフォーマットする方法
Pythonでは、辞書(dict)を活用して文字列への値の埋め込み(補間)を行うことができます。この構文では、%と変換文字の間の括弧内に、辞書のキー名を指定します。例えば、キーcostに格納された浮動小数点数を$xxxx.xxの形式で表示したい場合は、表示したい位置に$%(cost).2fと記述します。辞書を使った文字列フォーマットの基本例以下は、辞書を使った文字列フォーマットで、文字列と数値を同時に補間・整形する例です。>>> print(%(language)s has %(number)03d quote types. % {language: Python, numb