표현식 괄호


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(어떤 솔루션은 괄호로 ((1+2)+(3+4))
묶을

답변:


2

파이썬, 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

이 프로그램은 십진수 입력을 처리합니다.

두 번째 줄은 공백으로 시작하고 두 번째 줄은 탭으로 시작하고 세 번째 줄은 탭으로 시작하고 세 번째 줄은 공백으로 시작합니다. 이것은 1 바이트를 절약했습니다. 다음은 16 진수 덤프 ( 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이 색상에 이스케이프 코드를 사용하는지 확인하십시오 .


* 공간이있는 넷째?
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) is 4
edc65

3

자바 스크립트 (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]

다른 두 가지 답변이 모두 잘못되었으므로 글을 게시하겠습니다. 여기여기 그리고 다른 곳 에서 사용한 표현식 파서의 변형입니다 . 자세한 알고리즘 설명은 여기를 참조하십시오.

꽤 부피가 크지 만 작동해야합니다.

테스트 스 니펫

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) 라이브러리 와 homebrew 문자열 대체 dict을 사용하고 있습니다. 문자열 교체 비용은 많이 들지만 보너스는 점수를 다소 낮게 유지하는 데 도움이됩니다. 어쩌면 (끈 교체 부분) 골프를 더 할 수 있습니다.

이 솔루션은 각 숫자 주위에 여분의 괄호 세트를 추가하지만 질문의 정신 안에 있다고 생각합니다.

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 (수입 라인 추가 후 더 많은 것)이어야합니다. 좋은 점수입니다-만약 당신이 고치면
공감하겠습니다

좋은 지적. 가져 오기를 추가했습니다. 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.