주문의 조작 프로그램을 생산하는 임무. 당신의

소개

어린 시절에 더하기와 곱하기를 마스터했다고 생각하면 누군가가 와서 다음과 같이 알려줍니다.

a * b + c = (a * b) + c! = a * (b + c),

이전에 배운 것만 큼 간단하거나 선형 적이 지 않았습니다. 작업 순서 라는 것이 있다는 것을 알게 됩니다 . 이것은 괄호가 모든 것을 방해하지 않고 일정 수준의 일관성과 표현을 유지하는 매우 중요한 방법입니다.

일반적인 스토리

어느 날, 당신은 거리에서 공황의 소리에 일어납니다. ” 2560 ” 이라는 이름의 극단주의 단체 (도덕적 인 육십이를 가진 “작전 조직에 대한 조직”의 짧은)는 그들의 사악한 방법을 사용하여 세계의 모든 핵무기를 통제했습니다. 그들은 전체 행성 인질을 보유하고 있으며 간단한 요구가 있습니다. 수용 된 순서를 바꾸거나 박멸하십시오 (괄호는 우선 순위를 유지해야 함). 새로운 시스템을 PSADME (괄호, 뺄셈 / 더하기, 나누기 / 곱하기, 지수)라고하며 식은 오른쪽에서 왼쪽으로 평가됩니다.

a - b - c = a - (b - c) = a + c - b

일이 지나고 전환이 진행 중입니다. 수학자와 물리학 자들이 모두 방정식을 다시 작성하는 데 바쁘지만 컴퓨터 과학자들은 컴퓨터가 수학 표현을 해석하는 방식을 바꾸는 작업에 직면하고 있습니다. 우연히하고, 당신이 무작위로 선택됩니다 – 당신은 원인의 목표는 많은 새로운 글로벌 군주에 대한 고통으로 비밀 반군 프로그램 그룹에 속한 2560 및 벤치 마크 계산 프로그램을 생산하는 임무.

당신의 임무

(숫자) 수학 표현식을 입력으로 사용하고 PSADME 를 연산 순서로 사용하여 표현식을 계산 하고 결과를 출력 하는 프로그램 (또는 함수)을 작성하십시오 . 식은 오른쪽에서 왼쪽으로 평가되므로

1−삼+4=1−7=−6.

간단히하기 위해 제공된 모든 숫자는 정수가되고 계산은 정수 결과를 생성합니다.

규칙과 득점

  • 프로그램은 최대 128 자 길이의 입력을 허용해야합니다. 언어 / 플랫폼의 최대 입력 길이가 낮은 경우 허용 가능한 변명입니다.
  • 표준 허점은 금지되어 있습니다.
  • 당첨 코드는 11 월 18 일 (이 게시물 날짜부터 4 주)에 선택됩니다.
  • 골프에 적합하지 않은 코드를 게시하십시오. 이것은 재미에 관한 것입니다. 이 작업을 수행하는 데 흥미로운 방법이 있지만 직접 골프를 칠 수 없거나 방법의 특성에 따라 게시 할 수 있다면 어쨌든 게시 할 수 있습니다.

평소와 같이 당첨 코드는 바이트 수가 가장 적고 엔터테인먼트 가치 보너스가있는 코드입니다.

  • 제공된 표현식에서 문자를 사용하지 않으려면 -5 : + , , ( , ) , ^ , * , /
  • -5 계산 방법이 명확하지 않은 경우 (클럭 또는 불필요한 루프 사용) 표준 컴퓨터에서 계산하는 데 5 분 (10 분 이하)이 소요됩니다. 목표는 당신이되지 않는다는 새로운 군주를 설득하는 노력 운명의 자신의 계산을 방해 할 수 있습니다.
  • -(5 + N) 2560의 멤버에 대한 직접적인 공격 메시지 (길이 N, 선행 / 트레일 링 공백 제외)의 경우 코드 내에서 명확하게 볼 수있는 2560 멤버에 대한 이유와 함께 우스운 설명 그곳에. 코드가 제거되면 코드 올바르게 작동 하지 않아야 합니다. 예, 엔터테인먼트 가치에 대한 무료 포인트.

예와 설명

[program] 2 - 2 - 2
2

2-(2-2) = 2

[program] (2 + 2 * 3 + 3) / 3 + 3
4

(4 * 6) / (3 + 3) = 4

[program] 3 + 2 + 1 ^ 3
216

(3 + 2 + 1) ^ 3 = 216

[program] -5^2
25

(-5) ^ 2 = 25

[program] 32 / 8 * 3 - 1
2

32 / (8 * (3-1)) = 32/16 = 2



답변

하스켈, 134 바이트

import qualified Prelude as P
infixl 6 ^
(^)=(P.^)
infixr 8 +
(+)=(P.+)
infixr 8 -
(-)=(P.-)
infixr 7 /
(/)=P.div
infixr 7 *
(*)=(P.*)

새로운 연산자와 우선 순위를 사용하여 수학 연산자를 재정의합니다. 지금:

*Main> 32 / 8 * 3 - 1
2

답변

exec 확장자를 가진 GNU sed -r, 398

s@ *\^ *@ ** @
:
s@\((-?[0-9]+)\)@\1@
t
s@(-?[0-9]+ - )+(-?[0-9]+ - -?[0-9]+)@\1(\2)@
t
s@(.*(^| |\())(-?[0-9]+ [-+] -?[0-9]+)(.*)@echo '\1'$((\3))'\4'@e
t
s@(-?[0-9]+ / )+(-?[0-9]+ / -?[0-9]+)@\1(\2)@
t
s@(.*(^| |\())(-?[0-9]+ [*/] -?[0-9]+)(.*)@echo '\1'$((\3))'\4'@e
t
s@(-?[0-9]+ \*\* )+(-?[0-9]+ \*\* -?[0-9]+)@\1(\2)@
t
s@(.*(^| |\())(-?[0-9]+ \*\* -?[0-9]+)(.*)@bash -c 'echo \1$[\3]\4'@e
t

특히 짧지는 않지만 작업을 완료합니다.

sed는 우선 순위를 파싱해도 괜찮지 만 산술을하지 않습니다. 따라서 우리는 s명령에 GNU sed exec 확장을 사용하여 필요한 산술을 쉘에 아웃소싱합니다.

^앞뒤에 정확히 하나의 공백이 있는 것을 제외하고 모든 연산자를 가정합니다 .

테스트 출력 :

$ cat psadme.txt
2 - 2 - 2
(2 + 2 * 3 + 3) / 3 + 3
3 + 2 + 1 ^ 3
-5^2
32 / 8 * 3 - 1
$ sed -rf psadme.sed psadme.txt
2
4
216
25
2
$

답변

자바 스크립트 (ES6) 287 (300)

편집 코드 조각의 끝 부분에 대한 자세한 설명을 추가 – 버그 수정 (단지 오타는 6 4 있었어야)

편집 2 다른 도전에 대한 개선 사항을 발견했습니다

그러나 약간의 차이가 있지만 동일한 파서의 또 다른 포팅. (비교 )

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

// More readable
U=(x,W=[],Q=['('],z=1,
  h=p=>'+-*/^^))('.indexOf(p)>>1,
  C=n=>{
    for(;h(q=Q.pop())<h(n);
        W.push(q=='^'?Math.pow(a,b):eval(`a${q}b`)))
      a=W.pop(b=W.pop());
    z&&Q.push(q,n)
  }
)=>(
  (x+')')
  .replace(/\d+|\S/g,t=>
       t>'('
       ?t>'('
       ?~h(t)
       ?z&&t=='-'?z=-z:C(t,z=1)
       :(W.push(z*t),z=0)
       :C(t,z=0)
       :(Q.push(t),z=1)
  ),
  W.pop()
)

// TEST
console.log=(...x)=>O.innerHTML+=x.join` `+'\n'

console.log(f('1 - 3 + 4')) // -6
console.log(f('2-2-2')) // 2
console.log(f('(2 + 2 * 3 + 3) / 3 + 3')) // 4
console.log(f('3 + 2 + 1 ^ 3')) // 216
console.log(f('-5^2')) // 25
console.log(f('32 / 8 * 3 - 1')) // 2

// Explained
X=(x,W=[],Q=['('],z=1,
  h=p=> // operator priority '+-:1, */:3, ^:5, ):7, (:9. If an operand then -1
     '+-*/^^))('.indexOf(p)>>1,
  C=n=>{ // Evaluate operators present on stack if they have upper priority, then push new operator on stack
    //console.log('Operand '+n)
    while( h(q = Q.pop()) < h(n) ) // pop operator from op stack and compare priority with current
    {
      // Pop operands from stack and push result
      b = W.pop();
      a = W.pop();
      r = q=='^' ? Math.pow(a,b) : eval('a'+q+'b')
      // console.log('Evaluate '+a+q+b+'='+r)
      W.push(r);
    }
    // if z == 0 do nothing, because the current operands are '(' and ')' that must be discarded
    // else Push again the last operator popped and the current one
    z && Q.push(q, n) // 
  }
)=>(
  (x+')')
  .replace(/[\d.]+|\S/g,t=> {
    //console.log('Q:'+Q,'W:'+W,'T:'+t,'U:'+h(t),'Z:'+z), // display status
    if (t == '(')
    { // open parenthesis
      z = 1
      Q.push(t) // push a operator, its the highest priority
    }
    else if (t == ')')
    { //close parenthesis
      z = 0
      C(t)
    }
    else if (h(t) < 0)
    { // operand
      W.push(z*t) // push operand with right sign
      z = 0 // set z to 0 to mark that we just pushed an operand, so next '-' (if present) is a binary operator 
    }
    else
    { // operator
      if (z && t=='-') // the minus is an unary operator (the only unary operator allowed is '-', '+' will not work)
        z =-z // change the sign
      else
        z = 1, // no unary minus
        C(t)
    }
  }),
  W.pop() // return the value at top of operand stack
)
<pre id=O></pre>