前回の逆ポーランド記法プログラムの改良版

前回のプログラムの問題点

apple + lemmon

逆ポーランド変換記法に変換しようとすると

['a', 'p', 'p', 'l', 'e', 'l', 'e', 'm', 'm', 'o', 'n', '+']

となってしまう点を何とか解決。使ったのは正規表現で、集合とは特に関係なかった。プログラムは

def reverse_polish():
    LIST = list()    #リスト作成
    read_a_line(LIST) #一行読み込む
    skip_spaces(LIST) #空欄は削除する
    #ここから逆ポーランド変換
    List1 = []    #演算数を入れるリスト&逆ポーランド記法の結果が入る
    List2 = ['@'] #演算子を入れるリスト
    import re
    i,n = 0,len(LIST)-1
    while i <= n:
        if LIST[i] == "$": #$が入力されたら終了
            break
        elif re.findall("[a-z|A-Z|0-9]+", LIST[i]):
            List1.append(LIST[i])
        elif LIST[i] == '(':
            List2.append(LIST[i])
        elif LIST[i] == ')':
            while not List2[len(List2)-1] == '(':
                List1.append(List2[len(List2)-1])
                del(List2[len(List2)-1])
            del(List2[len(List2)-1])
        elif LIST[i] in ('+','-','*','/'):
            while less_or_equal_prec(LIST[i],List2[len(List2)-1]):
                List1.append(List2[len(List2)-1])
                del(List2[len(List2)-1])
            List2.append(LIST[i])
        i = i + 1
    while not List2[len(List2)-1] == '@':
        List1.append(List2[len(List2)-1])
        del(List2[len(List2)-1])
    print List1 #逆ポーランド変換ここまで
    #ここから数字を計算する
    i,n = 0,len(List1)-1
    List3 = []  #ここに計算結果が入る
    while i <= n:
           if re.findall("[0-9]+",List1[0]):
                List3.append(List1.pop(0))
           elif List1[0] == '+':
                temp = int(List3.pop()) + int(List3.pop())
                List3.append(temp)
                del(List1[0])
           elif List1[0] == '-':
               temp = int(List3.pop(-2)) - int(List3.pop())
               List3.append(temp)
               del(List1[0])
           elif List1[0] == '*':
               temp = int(List3.pop()) * int(List3.pop())
               List3.append(temp)
               del(List1[0])
           elif List1[0] == '/':
               temp = int(List3.pop(-2)) / int(List3.pop())
               List3.append(temp)
               del(List1[0])
           i += 1
    if len(List3) == 1 #1個だけの時はちゃんと計算ができた
        return List3

stringモジュールに変えてreモジュールを使えば、

>>> a = "(abc+de*f)"
>>> b = re.findall("[a-z|A-Z]+", a)
>>> b
['abc', 'de', 'f']

のようにうまくアルファベットのみを抽出できたし、こうすれば

>>> c = re.findall("[a-z|A-Z|0-9]+|[^a-z|A-Z|0-9]+", a)
>>> c
['(', 'abc', '+', 'de', '*', 'f', ')']

これまたうまく変数になりそうなアルファベットと、その他の記号に分けることができた。これを使ってread_a_line関数をちょっと書き換える。

def read_a_line(list):
    #読み込んだ式をリストへ格納する
    import re
    temp = raw_input()
    inpt = re.findall("[a-z|A-Z|0-9]+|[^a-z|A-z|0-9]", temp)
    for i in inpt:
        list.append(i)


出力結果は

>>> reverse_polish()
Google + Microsoft
['Google', 'Microsoft', '+']
>>> reverse_polish()
12+(30-20)
['12', '30', '20', '-', '+']
[22]
>>> reverse_polish()
(324/2)*(42-21)+13
['324', '2', '/', '42', '21', '-', '*', '13', '+']
[3415]


あとは' = 'を使った式を上手に表現したり、変数に値を代入できたりすればいいんだけど・・・。さてどうしたもんだろうかな。ちっとも見当が付かねえな。