订单操作


13

介绍

在童年时期,当您认为自己已经掌握了加法和乘法运算时,就会出现一个观点,然后有人来告诉您:

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

而且它不像您先前所讲的那样简单或线性。您了解到存在一种称为操作顺序的事物。这是保持某种程度的一致性和表达式的一种非常重要的方法,而不会让括号妨碍所有内容。

一般故事情节

有一天,你醒来时在街上惊慌失措。一个以“ 2560 ” 为名的极端主义团体(“反对行动组织”的简称,带有诡异的六角形扭曲)已经使用了邪恶的方法来控制世界上所有的核武器。他们束缚着整个星球的人质,他们有一个简单的要求:逆转公认的行动顺序或铲除面孔(括号是他们的首要任务)。新系统称为PSADME(括号,减法/加法,除法/乘法,指数),表达式从右到左求值:

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

几天过去了,过渡正在进行中。在数学家和物理学家都忙于重写方程式的同时,计算机科学家面临着改变计算机解释数学表达式的方式的任务。您属于一个秘密的反叛程序设计小组,该小组旨在给新的全球霸主造成尽可能多的折磨-偶然地,您被The 2560随机选中,并负责制定基准计算程序。

你的任务

编写一个程序(或函数),将一个(数值)数学表达式作为输入,使用PSADME作为运算顺序来计算该表达式并输出结果。表达式应从右到左求值,因此

13+4=17=6.

为简单起见,提供的所有数字均为整数,并且计算将得出整数结果。

规则和计分

  • 该程序应接受最多128个字符的输入-如果您的语言/平台的最大输入长度较短,那是可以接受的借口。
  • 禁止出现标准漏洞。
  • 获奖代码将在11月18日(从发布日期起4周)内进行选择。
  • 随意发布不被认为是值得高尔夫的代码。这是关于乐趣。如果您有一种有趣的方式进行此操作,但不能自己打高尔夫球(或根据方法的性质),则可以将其发布。

按照惯例,获胜的代码是字节数最少的代码,并带有一些娱乐性价值的奖励:

  • -5用于避免在提供的表达式中使用任何字符:+-^*/
  • -5用于在标准计算机上进行超过5分钟(但不超过10分钟)的计算,而方法并不明显(使用时钟或不必要的循环);其目的是要说服新的霸主,你是不是破坏他们的死命的计算。
  • -(5 + N),用于在您的代码中清晰可见地写出有关2560成员的直接攻击性消息(长度N,不包括开头/结尾的空白),并对为什么需要将其作一些荒谬的解释那里。如果将其删除,则代码不能正确运行。是的,获得娱乐价值的免费积分。

例子和解释

[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


1 - 3 + 4 = 1 - 7?从右到左将表明是这样,但这与PSADME相反,是在加法之前加上加法,不是吗?
LLlAMnYP

1
@LLlAMnYP加法和减法在同一个“组”中,就像在PEMDAS中一样,因此它们从右到左发生。与乘/除相同。更像是P(SA)(DM)E
Geobits,2015年

2
该语句并不是要从右到左处理-而是将具有相同优先级的操作从右至右进行评估。所以4/2 = 2,2-1 = 1,但是a / b c = a /(b c)而不是通常的(a / b)* c。我希望这可以解决问题。
2015年

可能最简单的方法是编写flex / bison或lex / yacc语法。

5
您应该将首字母缩略词更改为PADME,因为这样一个邪恶组织的成员肯定会比原来更喜欢新的《星球大战》三部曲。还容易记住。
mbomb007

Answers:


9

Haskell,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

1
哇。只是,哇。还有其他语言可能吗?+1
ETHproductions 2015年

我很确定,这在Mathematica中是可行的,或者至少是一种类似的方法,但是很快我意识到,我缺乏做到这一点的知识。
LLlAMnYP

1
我在这里很陌生,无法确定以下建议在此论坛上通常是否可以接受。它完全基于您的代码,但是是一个bash脚本,它使用Perl生成Haskell文件并将其传递给GHCi。这样,我保存了整个字节。 perl -e'$_="import qualified Prelude as Pl 6^r 8+r 8-r 7*r 7/";s/(. \d(.))/\ninfix\1\n(\2)=(P.\2)/g;s~\./~.div~;print'>a.hs;ghci a.hs 不幸的是,输入错误使生成的代码在数字和符号之间缺少空格,但仍然可以正常运行。这意味着您的代码可能会丢失5个字节,并且超出了我的“改进”。
2015年

@JArkinstall对于它的价值,我的回答是有效地sed用于生成和评估shell代码。可能是一个很好的元问题。
Digital Trauma 2015年

是的,我真的很喜欢您的方法-但是,使用工具(perl或sed)生成一种语言的文件,然后将其读为另一种语言似乎又向前了一步。如果存在通过另一种生成器生成上述代码的方法,我也不会感到惊讶(尽管该方法对我而言并不明显!),我们会发现自己处于解析接收状态。如果允许的话,甚至可以将此方法应用于您的代码(还有一些示例,我在一些可读性更好的语言答案中看到了一些有关此板的挑战)。
2015年

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扩展,以将必要的算法外包给shell。

现在假设所有运算符,除了^前后仅有一个空格外。

测试输出:

$ 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
$ 

不错的个人资料图片。xD
奥利弗·倪

1

JavaScript的(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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.