式を括弧で囲む


20

最近、新しい言語を書いています。操作の順序を処理する必要を避けるために、各式を適切に括弧で囲んで、これを完全に回避しています。

括弧は40〜41の文字コードであるため、コードはできるだけ短くする必要があります。


1+2*3
(1+(2*3))

2*(3+4)
(2*(3+4))

2*3/4+3
(((2*3)/4)+3)

342*32/8
((342*32)/8)

ルール

処理する必要がある操作は*/(乗算)、(除算)、+(加算)、および-(減算)のみです。

  • 操作順序は次のとおりです。
    • 括弧
    • 乗算、除算
    • 加算、減算
  • あなたは左右に行くことを好むべきです
  • 入力番号は常に正の整数になります(ボーナスを参照)

ボーナス

否定を処理する場合は-20%

3+-5
(3+(-5))

入力内にスペースを入れることを許可する場合、-5%

3  + 4
(3+4)

入力で小数を処理できる場合は-10%

1+.12
(1+.12)
1+0.21/3
(1+(0.21/3))

500バウンティ:無名 / ブロックで答えを書くことができた場合


25
「括弧は40〜41の文字コードであるため、コードはできるだけ短くする必要があります。」さて、あなたはただとんでもないことです。; P
ETHproductions

3
そして、これは接頭辞(ポーランド語)表記よりも簡単です。
wizzwizz4

3
重複する可能性があります。
flawr

8
@flawr私はそれを見ましたが、その質問はあなたが式を括弧で囲むすべての方法を出力するという事実で非常に異なっています。ここでは、私はコードのように有意差は自明この挑戦のために変更することはできませんと思う操作のアカウントの順に取らなければならない
Downgoat

3
重要なテストケース:1+2+3+4(特定のソリューションとしてparenthesiseかもしれない((1+2)+(3+4))
マーティン・エンダー

回答:


2

Python、153 * 0.9 = 137.7バイト

def p(e):
 for o in"+-*/":
    for i,c in enumerate(e):
        if(c==o)*(0==sum([(d=="(")-(d==")")for d in e[:i]])):return"("+p(e[:i])+o+p(e[i+1:])+")"
 return e

このプログラムは10進入力を処理します。

2行目はスペースで始まり、2行目はタブで始まり、3行目は2つのタブで始まり、3行目はスペースで始まります。これにより1バイト節約されました。hexdump(xxdpp)は次のとおりです。

0000000: 6465 6620 7028 6529 3a0a 2066 6f72 206f  def p(e):. for o
0000010: 2069 6e22 2b2d 2a2f 223a 0a09 666f 7220   in"+-*/":..for 
0000020: 692c 6320 696e 2065 6e75 6d65 7261 7465  i,c in enumerate
0000030: 2865 293a 0a09 0969 6628 633d 3d6f 292a  (e):...if(c==o)*
0000040: 2830 3d3d 7375 6d28 5b28 643d 3d22 2822  (0==sum([(d=="("
0000050: 292d 2864 3d3d 2229 2229 666f 7220 6420  )-(d==")")for d 
0000060: 696e 2065 5b3a 695d 5d29 293a 7265 7475  in e[:i]])):retu
0000070: 726e 2228 222b 7028 655b 3a69 5d29 2b6f  rn"("+p(e[:i])+o
0000080: 2b70 2865 5b69 2b31 3a5d 292b 2229 220a  +p(e[i+1:])+")".
0000090: 2072 6574 7572 6e20 650a                  return e.

テストに使用したプログラムは次のとおりです:(上記のプログラムをとして保存しますparen.py

import paren

cases = {
        "2+3*4": "(2+(3*4))", 
        "(2+3)*4": "((2+3)*4)", 
        "1+2+3+4": "(1+(2+(3+4)))", 
        "3/2+5": "((3/2)+5)", 
        "1+2-3": "(1+(2-3))", 
        "2-1+2": "((2-1)+2)",
        "3+-5": "(3+(-5))",
        "1+.12": "(1+.12)",
        "1+0.21/3": "(1+(0.21/3))",
}


for num, case in enumerate(cases):
    print "\n\n\033[1m\033[38;5;14mCase #%d: %s" % (num + 1, case)
    result = paren.p(case)
    print "\033[38;5;4mParenthesize returned: %s" % (result)
    solution = cases[case]
    if result == solution:
        print "\033[38;5;76mCorrect!"
    else:
        print "\033[38;5;9mNot correct!"

端末が\033[38;5;<COL>m色にエスケープコードを使用していることを確認してください。


* 4番目のスペースは?
Element118

1
このプログラムはそうではありませんprefer to go left-right。OPでテストケース3を試してください。結果は正しくありません。これは、たとえば整数演算の場合、実際の問題になる可能性があります。((2*(3/4))+3)!=(((2*3)/4)+3)
edc65

1
@ user12365 整数演算を使用していない(たとえばCまたはC ++で)3/4 == 0であるため、((2 *(3/4))+ 3)は3である一方、(((2 * 3)/ 4)+ 3)4
edc65

3

JavaScript(ES6)179(263 -20%-5%-10%)

(x,W=[],Q=['('],z=1,w=v='',h=p=>'*/+-))('.indexOf(p)|1,C=n=>{for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;z&&Q.push(q,n)})=>(x+')').replace(/[\d.]+|\S/g,t=>t>'('?t>')'?~h(t)?z?(w+='('+t,v+=')'):C(t,z=1):W=[w+t+v,...W,z=w=v='']:C(t,z=0):z=Q.push(t))&&W[0]

他の2つの答えは現在どちらも間違っているので、私は投稿します。これは、ここここと他の場所で使用した式パーサーのバリエーションです。より詳細なアルゴリズムの説明を参照してください。

かなりかさばりますが、動作するはずです。

テストスニペット

f=(x,W=[],Q=['('],z=1,w=v='',h=p=>'*/+-))('.indexOf(p)|1,C=n=>{for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;z&&Q.push(q,n)})=>(x+')').replace(/[\d.]+|\S/g,t=>t>'('?t>')'?~h(t)?z?(w+='('+t,v+=')'):C(t,z=1):W=[w+t+v,...W,z=w=v='']:C(t,z=0):z=Q.push(t))&&W[0]

// More readable
x=(x,W=[],Q=['('],z=1,w=v='',
  h=p=>'*/+-))('.indexOf(p)|1,
  C=n=>{
    for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;
    z&&Q.push(q,n)
  }
)=>(
  (x+')')
  .replace(/[\d.]+|\S/g,t=> 
       t>'('    
       ?t>')'
       ?~h(t)
       ?z
       ?(w+='('+t,v+=')')
       :C(t,z=1)
       :W=[w+t+v,...W,z=w=v=''] // overfill W to save 2 chars ()
       :C(t,z=0)
       :z=Q.push(t)
  ),
  W[0]
)

console.log=(...x)=>O.textContent+=x.join` `+'\n'

// TEST
;[
  ['1+2*3','(1+(2*3))'],['2*(3+4)','(2*(3+4))'],['2*3/4+3','(((2*3)/4)+3)'],['342*32/8','((342*32)/8)'],
  ['3+-5','(3+(-5))'],['-3+-4*7','((-3)+((-4)*7))'], // bonus 20%
  ['3  + 4','(3+4)'], // bonus 5%
  ['1+.12','(1+.12)'],['1+0.21/3','(1+(0.21/3))'] // bonus 10%
].forEach(t=>{var k=t[1],i=t[0],r=f(i); console.log(i+' : '+r+(r==k? ' OK':' Fail expecting '+k))})
<pre id=O></pre>


1

Python、241 * 0.8 * 0.95 * 0.9 = 164.84文字

私は、ast(Abstract Syntax Trees)ライブラリと自作の文字列置換辞書を使用しています。文字列の置換には多くの費用がかかりますが、ボーナスはスコアをいくぶん低く抑えるのに役立ちます。たぶん(ストリング交換部品)はさらにゴルフすることができます。

このソリューションでは、各番号の周りに括弧の余分なセットが追加されますが、それは質問の精神の範囲内だと思います

import ast;def p(e):
 r,s={"Module([":"",")])":"","Expr(":"","BinOp":"","Num":"",", Add(), ":"+",", Sub(), ":"-",", Div(), ":"/",", Mult(), ":"*"},ast.dump(ast.parse(e),annotate_fields=False)
 for f,t in r.iteritems():s=s.replace(f,t)
 return s

テストスイート:

cases = {
    "2+3*4", 
    "(2+3)*4", 
    "1+2+3+4", 
    "3/2+5", 
    "1+2-3", 
    "2-1+2",
    "3+-5",
    "1+.12",
    "1+0.21/3"
}

for num,case in enumerate(cases):
    result = p(case)
    print "Case {}: {:<16} evaluates to: {}".format(num+1,case,result)

テストスイートの出力:

Case 1: 3+-5             evaluates to: ((3)+(-5))
Case 2: 3/2+5            evaluates to: (((3)/(2))+(5))
Case 3: 2+3*4            evaluates to: ((2)+((3)*(4)))
Case 4: 1+2+3+4          evaluates to: ((((1)+(2))+(3))+(4))
Case 5: 1+0.21/3         evaluates to: ((1)+((0.21)/(3)))
Case 6: (2+3)*4          evaluates to: (((2)+(3))*(4))
Case 7: 2-1+2            evaluates to: (((2)-(1))+(2))
Case 8: 1+.12            evaluates to: ((1)+(0.12))
Case 9: 1+2-3            evaluates to: (((1)+(2))-(3))

ミッシングimport astコードの中で
edc65

そして、それはパーセントボーナスを獲得する正しい方法ではありません。50%の割引があり、さらに50%の割引がある場合、0は支払われていません。スコアは157.32(インポート行を追加した後の値)になります。それは良いスコアです-あなたが修正を加えた場合、私はupvoteよ
edc65

いい視点ね。インポートを追加しました。241文字になりました。ただし、ボーナスの計算方法がわかりません。私が正しくあなたのコメントを理解していれば、ボーナスが減算される順序は問題...
agtoever

ボーナスは減算されず(乗算)、順序は関係ありません。241 *(1-20%)*(1-5%)*(1-10%)=> 241 * 0.8 * 0.95 * 0.9 => 164.84
edc65

@ edc65ああ。右。まっすぐ考えていませんでした。ありがとう。
agtoever
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.