アルゴリズムを学習する【第2回:対応する括弧があるかどうかをチェックする】
エディター(Visual Studio Codeなど)を使って、コーディングをしていると対応する括弧(中括弧、丸括弧など)がない場合、「対応する括弧がありませんよ」と教えてくれる便利な機能があったりします。
今回は、このロジックを考えていきたいと思います。
スタック(データ構造)
基本的なデータ構造にスタックというのがあります。
スタックはデータの取り出し方に特徴があります。最後に入れたデータからしか取り出すことができないということです。
後入れ先出しなどと呼ばれたりしています。
例えば、下の絵のように、お皿を順番に積み上げていくと、後から置いたお皿からしか取っていけないといったイメージです。
このデータ構造を使って、対応する括弧があるかを判別していきます。
では、ロジックを考えていきたいと思います。
まず、データ構造のスタックをどこで使うかですが、 渡された文字列をひとつずつ見ていって、始め括弧が出てきた時に、スタック構造の配列(リスト)にその括弧を一時的に保存するときに使います。(このブログでは、実際は、その対応する終わり括弧を保存していきます。)
一時的に保存する配列(リスト)は、 要素の操作として、「末尾に追加」と「末尾から取り出して削除」することしか行わないことにします。
では、実際に考えていきたいと思います。
例えばこのような文字列があったとします。
(apple[orange])
この文字列の文字をひとつずつみていって、括弧があった場合に次のような処理を行っていきます。 1.始め括弧の「(」が出てきたので、スタック構造のリストに対応する終わり括弧「)」を入れます。 2.始め括弧の「[」が出てきたので、スタック構造のリストに対応する終わり括弧「]」を入れます。 3.終わり括弧「]」が出てきたので、スタック構造のリストの一番上のものを取り出して、比較します。 4.終わり括弧の「)」が出てきたので、スタック構造のリストから取り出して、比較します。

文字列のすべてをみていって、スタック構造のリストに何も残ってなければOKということになります。 この説明はエラーにならない場合になります。
反対にどういったときにエラーになるのかを考えておく必要もあります。
エラーになるパターン1
(apple[orange)
1.始め括弧の「(」がでてきたので、対応する「)」をスタック構造のリストに入れます。 2.始め括弧の「[」が出てきたので、対応する「]」をスタック構造のリストに入れます。 3.終わり括弧の「)」が出てきたので、スタックの一番上のものを取り出して比較します。

スタックの一番上は、「]」なので比較すると「)」 ≠ 「]」になるので、この時点でエラーとなります。
エラーになるパターン2
apple](orange)
終わり括弧が最初に出てくる場合は、スタック構造のリストに何も入っておらず、比較するものがないのでエラーとなります。
エラーになるパターン3
(apple)[orange
この場合は文字列すべてみ終わった時にスタック構造のリストに「]」が残ることになります。 文字列をすべて取り出し終わった後、スタック構造のリストの中に何かしら残っている場合はエラーとなります。
以上がエラーになる場合になります。(もしかしたら他にあるかもしれませんが。。。)
これをコーディングしていきます。
def check_format(chars):
# 括弧があるかどうかの判定用にオブジェクトを作成する
brackets = { '(': ')', '[': ']', '{': '}' }
# 配列(スタック構造)をつくる
stack = []
# 引数で渡されたcharsの文字列を一文字一文字を取り出していく
for char in chars:
# bracketsのkeyがあった場合
if char in brackets.keys():
# stackにkeyに応じたvalueを入れる
stack.append(brackets[char])
# bracketsのvalueがあった場合
if char in brackets.values():
# stackが空の場合
if not stack:
return "Error"
# stackから取り出したものと比較する(比較したものが同じであればforループを続ける)
if char == stack.pop():
continue
else:
return "Error"
# 文字列をすべてみたあと
# stackに何かしら残っている場合はError
if stack:
return "Error"
return "OK"
if __name__ == '__main__':
s = '[apple(orange)]'
print(check_format(s))
この部分は
if char == stack.pop():
continue
else:
return "Error"
次のようにも書けます。
if char != stack.pop()
return "Error"
以上となります。 今回は、スタック構造を使ったロジックを考えてみました。

