젠장, 수학 좀 해봐!


19

PEMDAS 연산 순서는 수행해야하는 순서 연산을 알려주는 수학의 기본 규칙입니다.

"부호, 지수, 곱셈과 나눗셈, 덧셈과 뺄셈"

문제는 PEMDAS가 매우 다양하지 않다는 것입니다! 다른 순서로 수행하려면 어떻게해야합니까? 우리는 괄호를 엉망으로 만들지 않기 때문에 괄호를 (첫 번째) 위치에 유지합니다.

두 가지 인수를 취하는 프로그램을 작성하십시오.

  • 작업 순서를 알려주는 문자열입니다. 몇 가지 예는 "DAMES", "SAD, ME", "ME SAD", "MEADS". 예, 공백과 쉼표는 순서를 기억하기 쉽기 때문에 괜찮습니다.
    • 채팅시 제안 사항 : 공백과 쉼표 지원은 이제 선택 사항입니다.
    • 문자 중 하나가 누락되었거나 추가 문자가 없어야하는 경우 입력을 유효하지 않은 것으로 간주하고 원하는대로 처리 할 수 ​​있습니다.
  • 평가할 표현식이 포함 된 문자열 또는 표현식입니다.

표현식의 결과를 10 진수 또는 정수로 리턴하십시오. 답변이 정수가 아닌 경우 10 진수로 반환해야합니다.

규칙 :

  • 귀하의 언어에서 더 쉬운 경우 두 입력 인수를 하나로 결합해도됩니다.
  • 문자열 일 필요는 없지만 문자가 있어야합니다. 덧셈을 1로, 나눗셈을 2로 등을 대체 할 수 없습니다.
  • 가장 먼저 입력을 선택할 수 있습니다.
  • 표현식은 오른쪽에서 왼쪽으로 오른쪽에서 평가 됩니다. (규칙 변경. 다른 방식으로 처음 12 시간 동안 제출 한 모든 포스터는 수락됩니다.)
  • 조작은 다음 기호를 사용합니다 ( ) ^ * / + -.. 예를 들어, 추가 ¤대신 사용할 수 없습니다 +.
  • 입력 표현식의 공백이 입력으로 유효하지 않습니다
  • 단항 +/-는 + 또는-바로 뒤에 오는 경우 입력으로 유효하지 않습니다. 3+-2유효하지 않은 입력으로 간주하십시오 . 그러나 원하는대로 처리 할 수 ​​있습니다 (오류가 발생하지 않아도 됨). 경우 +또는 -플러스 또는 마이너스 이외의 연산자를 다음, 그것은 일반적인 방법으로 처리됩니다 : 3*-3 = -9,sin(-2)=-0.909
  • 프로그램은 반드시 문자를 따라야합니다 . "EMDAS", 1-3+4 => -6그리고 "EMDSA", 1-3+4 => 2.

예 :

Input:   "EMDAS", "3+6*2/4-1"   // -> 3+12/4-1 -> 3+3-1 -> 6-1 -> 5
Output:  5

Input:   "DAMES", "3+6*2/4-1"   // -> 3+6*0.5-1 -> 9*0.5-1 -> 4.5-1 -> 3.5
Output:  3.5

Input:   "SAD, ME", "3+6*2/4-1"  // -> 3+6*2/3 -> 9*2/3 -> 9*0.66667 -> 6   
Output:  6

Input:   "ME ADS", "3+5^4/2-3*2 // -> 3+5^4/2-6 -> 3+625/2-6 -> 628/2-6 -> 314-6 -> 308
Output:  308

Input:   "AM EDS", "4*3-sin(0.5^2)*3+1" // -> 4*3-sin(0.5^2)*4 -> 12-sin(0.5^2)*4 -> 4*3-(4*sin(0.5^2)) -> 12-(4*sin(0.5^2)) -> 12-(4*sin(0.25)) -> 12-(4*0.24740) -> 12-0.98961 -> 11.01038
Output:  11.01038

Input:   "DAMES", "4-5-6"   // -> (4-5)-6 -> = -7  
Output:  -7                  // NOT: -> 4-(5-6) -> 4-(-1) -> 5

괄호를 추가 4*sin(0.5^2)하면 지수화 전에 곱셈 이 평가됨 을 나타냅니다 .

이것은 코드 골프이므로 바이트 단위의 가장 짧은 코드가 이깁니다.


2
완전히 동일하지는 않지만 이 과제 는 다른 작업 순서로 변경하는 것과 관련이 있으며 비슷한 일을하는 아이디어를 좋아하게 만드는 영감이었습니다. Haskell의 대답은 아마도이 질문에 대답하기 위해 재 작업 될 수 있다고 생각합니다 ... 엄격한 복제인지 확실하지 않은 경우, 연산자를 직접 변경할 수있는 기본 능력 없이이 도전을 수행하는 아이디어가 아주 좋습니다!
Dom Hastings

2
함수에 대한 보너스가 제거되었지만 예제에는 여전히 sin ()이 있습니다.
edc65

앞서 언급 한 도전보다 다소 악의적이며, 나는 그것을 복제본으로 경쟁하지 않을 것입니다 (원본에 대한 링크는 높이 평가되었을 것입니다). 그러나 모든 사람들이 The 2560 의 사악한 감독은 @Stewie Griffin 외에는 아무도 없습니다. 나는 놀랄 일이 아닙니다.
Jake

영국에서는 종종 학교에서 BODMAS또는 BIDMAS학교에서 배웁니다 . B= 대괄호 O또는 I= 주문 또는 지수.
BadHorsie

되어 p필요? 그것은 예에없는
ev3commander

답변:


7

자바 스크립트 (ES6) 349 353 387 400

... 아마도 여전히 골프

이 오래된 파서는 때때로 유용합니다-(이미 다른 두 가지 과제에서 이미 사용되었습니다)

E=
(d,x,W=[],Q=['_'],h={'(':1,_:8,')':7},z=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());Q.push(q,n)})=>([...d].map(l=>h[l='+-/*^'['ASDME'.search(l)]]=(d+=!!l),d=1),(x+')').replace(/\D|\d+/g,t=>(u=~~h[t])-1?u-7?u?z&&t=='-'?z=-z:C(t,z=1):(W.push(z*t),z=0):Q.pop(Q.pop(C(t),z=0)):z=!!Q.push('_')),W.pop())

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

console.log(E('MDASE','3+4*5^2'))
console.log(E("EMDAS", "3+6*2/4-1")) // 5
console.log(E("DAMES", "3+6*2/4-1")) //3.5
console.log(E("SAD, ME", "3+6*2/4-1")) // 6
console.log(E("ME ADS", "3+5^4/2-3*2")) // 308
console.log(E("AM EDS", "4*3-sin(0.5^2)*3+1")) // 11.01038 sin not supported
console.log(E("DAMES", "4-5-6")) // -7

// MORE READABLE
U=(d,x,W=[],Q=['_'],h={'(':1,_:8,')':7},z=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());
    Q.push(q,n)
  }
)=>(
  [...d].map(l=>h[l='+-/*^'['ASDME'.search(l)]]=(d+=!!l),d=1),
  (x+')').replace(/\D|\d+/g,t=> 
     (u=~~h[t])-1
       ?u-7
         ?u
           ?z&&t=='-'?z=-z:C(t,z=1)
           :(W.push(z*t),z=0)
         :Q.pop(Q.pop(C(t),z=0))
       :(Q.push('_'),z=1)
  ),
  W.pop()
)
<pre id=O></pre>

언 골프

Evaluate=(oprec,expr)=>
{
  var tokens = expr.match(/\D|\d+/g).concat(')')
  var t,a,b,v, SignV
  var vstack=[]
  var ostack=['_']
  var op={ '(':8, _: 1, ')':2}
  oprec.match(/\w/g).map((l,p)=>op['+-/*^'['ASDME'.search(l)]]=7-p)
  var OPush=o=>ostack.push(o)
  var OPop=_=>ostack.pop()
  var VPush=v=>vstack.push(v)
  var VPop=v=>vstack.pop()

  var Scan=i=>
  {
    SignV = 1
    for (; t=tokens[i++]; )
    {
      if (t == '(')  
      {
        OPush('_')
        SignV = 1
      }
      else if (t == ')')
      {
        CalcOp(t);
        OPop();
        OPop();
        SignV = 0
      }
      else if (op[t])
      {
        if (SignV && t=='-')
          SignV = -SignV
        else
          CalcOp(t), SignV = 1
      }  
      else
      {
        VPush(SignV*t)
        SignV=0
      }
    }
  }
  var CalcOp=nop=>
  {
    for (; op[po = OPop()] >= op[nop];)
      b=VPop(), a=VPop(), CalcV(a,b,po);
    OPush(po), OPush(nop);
  }
  var CalcV=(a,b,o)=>
  {
//    console.log('CV',a,b,o)
    if (o=='+')
      a+=b
    if (o=='-')
      a-=b
    if (o=='*')
      a*=b
    if (o=='/')
      a/=b
    if (o=='^')
      a=Math.pow(a,b)
    VPush(a)
  }
  Scan(0)

  return VPop()
}

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

console.log(Evaluate('MDASE','3+4*5^2'))
console.log(Evaluate('EMDAS','3+6*2/4-1')) // 5
console.log(Evaluate("DAMES", "3+6*2/4-1")) //3.5
console.log(Evaluate("SAD, ME", "3+6*2/4-1")) // 6
console.log(Evaluate("ME ADS", "3+5^4/2-3*2")) // 308
console.log(Evaluate("AM EDS", "4*3-sin(0.5^2)*3+1")) // 11.01038 sin not supported
console.log(Evaluate("DAMES", "4-5-6")) // -7
<pre id=O></pre>


(t=>t=='('?(z=1, Q.push('_'))모든 줄 바꿈과 함께 에서 공백을 제거 할 수 있다고 생각합니다 .
Conor O'Brien

1
@ CᴏɴᴏʀO'Bʀɪᴇɴ 님이 작업 중입니다. 감사합니다
edc65

난 당신이를 변경할 수 있습니다 생각 Math.pow(a,b)a**b
Kritixi LITHOS

@KritixiLithos 네, 더 이상 ES6이 아닙니다
edc65

6

R 3.3.2 : 209 196 187 177 바이트

비 산술 연산자 <, &, |, ~,?를 "오용"하는 것이 아이디어입니다. 우선 순위를 알고 ( ?SyntaxR-그러나 재정의 전; 참조) 주어진 산술 연산자로 재정의합니다. 매핑은 원하는 작업 순서에 따릅니다.

입력에서 공백과 쉼표는 지원 되지 않습니다 .

골프 버전

f=function(a,b){s=substr;l=list(E='^',M='*',D='/',A='+',S='-');q="<&|~?";for(i in 1:5){x=s(q,i,i);y=l[[s(a,i,i)]];assign(x,.Primitive(y));b=gsub(y,x,b,,,T)};eval(parse(text=b))}

Ungolfed 및 댓글 :

f = function(a,b) {
  s = substr
  # All arithmetic operators
  l = list(E = '^', M = '*', D = '/', A = '+', S = '-')
  # Some non-arithmetic R operators in descending precedence
  q = "<&|~?"
  for (i in 1:5) {
    # The substituted symbol
    x = s(q, i, i)
    # The original operator which has to be substituted
    y = l[[s(a, i, i)]]
    # Substitute the operator for the R interpreter
    assign(x, .Primitive(y))
    # Substitute the operator in the input string
    b = gsub(y, x, b, , , T)
  }
  # Parse and evaluate
  eval(parse(text = b))
}

예 :

> f("EMDAS", "3+6*2/4-1")
[1] 5
> f("DAMES", "3+6*2/4-1")
[1] 3.5
> f("SADME", "3+6*2/4-1")
[1] 6
> f("MEADS", "3+5^4/2-3*2")
[1] 308
> f("AMEDS", "4*3-sin(0.5^2)*3+1")
[1] 11.01038
> f("DAMES", "4-5-6")
[1] -7
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.