裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

ちょっと奇妙な足すと引く

2017年02月02日 | ブログラミング

ちょっと奇妙な足すと引く
締め切りが 2017/02/02 10:00 AM なので,その 1 分後に投稿されるように予約

【概要】
ここはとある遠い世界。この世界にも数式があり、足し算と引き算があります。
  19+2-3-4
こんな具合。この式を、我々の世界では
  ((19+2)-3)-4
と解釈して
  19+2-3-4 = 14
とするけど、この世界では
  19+(2-(3-4))
と解釈して
  19+2-3-4 = 22
となります。

要するに、「+と-の優先順位は同じで両方とも右結合」ということです。
で。
数式を与えます。この世界のルールで計算してください。

【入出力】
入力は
19+2-3-4
のような感じです。

演算子は+と-しか登場しません。括弧があることもあります。
1-4のように、計算結果が負の値になる場合には、我々の世界と同様に数字の前に「-」をつけて-3のようにしてください。
そうそう。言い忘れていましたが、数字はこの世界でも 10進数で、同じ記号を使います。

出力は計算結果になります。

【例】
入力        出力
19+2-3-4     22
1-4        -3
2-(2-2)-2     4

【補足】
    不正な入力に対処する必要はありません。
    入力文字列の長さは、1〜32 文字です。
    入力に含まれる数は、十億以下 です。
    入力文字列に、符号を示すマイナスは含まれません。

=======

入力をパースして逆ポーランド記法で表現し,それをスタックを使って数式を評価する

f = function(s) {
    s = gsub("([-\\+()])", " \\1 ", s)
    s = gsub("  *", " ", s)
    s = unlist(strsplit(s, " "))
    parse = stack = NULL
    for (t in s) {
        if (grepl("[0-9]+", t)) {
            parse = c(parse, t)
        } else if (t == "(") {
            stack = c(t, stack)
        } else if (t == ")") {
            repeat {
                if (length(stack) == 0) {
                    break
                }
                top = stack[1]
                stack = stack[-1]
                if (top == "(") {
                    break
                }
                parse = c(parse, top)
            }
        } else {
            stack = c(t, stack)
        }
    }
    parse = c(parse, stack)
    stack = NULL
    for (t in parse) {
        if (grepl("\\-*[0-9]+", t)) {
            stack = c(t, stack)
        } else {
            if (length(stack) > 1) {
                ans = eval(parse(text=sprintf("%s%s%s", stack[2], t, stack[1])))
                stack = stack[-1]
            } else {
                ans = stack[1]
            }
            stack[1] = ans
        }
    }
    cat(stack)
}
#f(readLines(file("stdin", "r")))

f("19+2-3-4") # 22
f("19+(2-(3-4))") # 22
f("6-1-4-4-8-4-6-3-5-8-7-9-9-2-7-8") # 13
f("8-9+6+9+5+1+6-1-4-2+4+8-2+1+5+4") # -29
f("3+3-1-6+7-5+5+9+2+4-8+3+1-4+5+5") # -9
f("6-68-47-3-76-52-78-15-20-99-58") # 48
f("23+13+85-49+41+64+69-0+50-34-93") # 7
f("12-(3-4-(5-6-7)-8-(9-10-11))-123") # 128
f("9-(((((((((((((34)))))))))))))-1") # -24
f("987-(12-(3-45-6)-7-8)-9-(123+45)") # 781
f("(9-10)-(2-5)-(7-9)-(7-45)-(3-39)") # 2
f("(((((((99-8)-7)-6)-5)-4)-3)-2)-9") # 55
f("999999999+999999999+999999999+99")  # 3000000096
f("1000000000-(99-19-3)+(88-32-11)") # 999999850

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 円周率に近似できる分数 | トップ | スーパー素数 »
最新の画像もっと見る

コメントを投稿

ブログラミング」カテゴリの最新記事