裏 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でシェアする

テキストから数値のみマスクしよう

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

テキストから数値のみマスクしよう

締め切りが 2017/02/02 10:00 AM なので,その 1 分後に投稿されるように予約

あなたはとあるレポートを文章校正のため社外の機関に送るよう任されました。
ただしレポートに含まれる数値は機密情報のため、すべてマスクする必要があるとのこと。

さらに桁数すらわからないようにとのお達しのため、単純に数字(0-9)を記号に置換するだけというわけにもいきません。
そこで、テキストから数値のみを検出し、*(アスタリスク)一文字に置換するプログラムを作ることになりました。

求められるプログラムの前提条件は、以下の通りとなります。

    標準入力から、制御文字を除くASCII文字のみで構成された文字列が送られる
    ※制御文字は入らないため、改行も含まれない
    文字列は80byte以下とする
    文字列に含む、すべての数値を*(アスタリスク)一文字に置き換える
    数値とは、整数・小数点数・"2.43E-19"といった指数表記による数のことを指す
    数の前に符号(-もしくは+)がある場合、符号も含めて数値とみなす
    指数表記におけるEは小文字・大文字双方とも扱うものとする
    すべての数値を*に置換した文字列を標準出力に返すこと

以下、置換例となります。

【入出力サンプル】
標準入力
x=12 y=-34.5 z=7e-8

標準出力
x=* y=* z=*

企業において、この数値をマスクするという作業は、実は社外だけではなく他部署に向けて公開する場合でもよくあることです。
例えば、特定プロジェクトの売上といったセンシティブな情報は、社内とはいえ取り扱いを厳重にしないといけない為です。

本当はこの機能、某社のOffice製品にこそあれば…おっとつい脱線しましたね。
是非挑戦してみてください!

【問題】
標準入力から、制御文字を除くASCII文字のみで構成されたテキストが送られます。
このテキストから数値のみを検出し、*(アスタリスク)一文字に置き換えて、その結果を標準出力に返してください。

============================

数を表す正規表現を正確に定義できるかどうかということ

s = readLines(file("stdin", "r"))
cat(gsub("(\\+|-)?[0-9]+((\\.[0-9]+)?((E|e)(\\+|-)?[0-9]+)?)?", "*", s))

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村