7
\$\begingroup\$

CAPTCHA Modified by Evil Mathematician

I accidentally incurred the wrath of an eccentric passive-aggressive mathematician. As part of his demented idea of payback, he modified the CAPTCHA system on my favorite website. Up until now, it would just ask a moderately challenging math question, like 3+2^4, and I would simply type the answer, 19, to verify that I am a human being. But now, thanks to my mathematical nemesis, the CAPTCHA questions are obnoxiously hard to calculate by hand and it keeps me from logging into my profile!

Math Captcha

From what I can tell, this is what he has done. The CAPTCHA images seem to still be the same, but the way it calculates the correct answer has changed. It takes the expression displayed in the image and rotates the operations. You wouldn't believe how long it took me to figure this out T__T.

Because of this fiasco, I need a program/function that takes in one of these expressions as a string, evaluates it and returns the result so that I can log onto my website! To make this a game, fewest bytes win.

Ok, you have the idea, lets walk through an example. Suppose that the CAPTCHA displayed an image with 6+5+4-3*2/1. Normally the answer would 9. Instead, we now have to rotate the operations to the right and that gives us 6/5+4+3-2*1. At this point, we evaluate it to be 6.2

Summary

Steps to evaluate the string input:

  1. Rotate the operation to the right
  2. Evaluate the result

Specifications

  • Full program or function
  • Standard I/O
  • Takes an expression
  • Prints/Returns the evaluated result
    • After the op rotation
  • Possible operations are +-/*^
    • The negatives for negative numbers stays with the number when rotating
    • Follow the normal order of operations after the rotation is completed
    • Using integer division is allowed
  • Possible numbers are positive/negative integers
    • This does not include 0
  • Parentheses could be included, but aren't rotated

Test Cases

Input     -> Output
1+3       -> 4
7+6       -> 13
1+1-2     -> 2
3*4+2     -> 11
-7^4      -> -2401
3*7+1-3   -> -1
-9+4/4    -> 1.75
(4*1)+8   -> 40
1+2-3*4/5 -> -16.5
1+-2*3    -> 1
3*4--2    -> 11
30-2/7    -> 8
120*3-4+10-> 122
(13^-12)+11 -> 1

Update

  • [16-07-28] Fixed typo in last test case. I had posted the expression after rotating it once >___> , so that rotating a second time gave an incorrect answer. It is fixed now! Thanks to @sintax!
  • [16-08-13] Removed broke test case. Thanks again to @sintax!
\$\endgroup\$
  • 2
    \$\begingroup\$ This question seems awfully familiar to me for some reason. It's like I saw this exact same question somewhere on PPCG some time ago...strange. \$\endgroup\$ – R. Kap Jul 28 '16 at 3:06
  • \$\begingroup\$ Integer division allowed? \$\endgroup\$ – Leaky Nun Jul 28 '16 at 3:06
  • \$\begingroup\$ How long did it take you to derive that last equation?! \$\endgroup\$ – R. Kap Jul 28 '16 at 3:14
  • 1
    \$\begingroup\$ @R.Kap That last one was a doozy, but who can say no "2 pi"? \$\endgroup\$ – NonlinearFruit Jul 28 '16 at 3:30
  • 2
    \$\begingroup\$ That overload of - as a negative number indicator and the subtraction operator makes this problem much harder/longer than it otherwise would be... \$\endgroup\$ – sintax Jul 28 '16 at 14:52
2
\$\begingroup\$

Dyalog APL, 30, but soon to be 16 bytes

⍎w⊣((w∊f)/w)←¯1⌽w∩f←'+-×÷'⊣w←⍞

Ungolfed, explained version:

w ← ⍞ Prompt for input (of the expression) and assign to w

f ← '+-×÷' assign the symbols to f

((w ∊ f) / w) ← ¯1 ⌽ w ∩ f using membership of f as mask, reassign those positions in w to the corresponding character in the cyclic 1-step-right rotated intersection of w and f (the symbols)

⍎w execute the modified expression

There is no special handling of minus/negative, because APL uses the distinct symbols - and ¯.

See the rotation of symbols on TryAPL!

In version 16 it will be much shorter as a function which takes the expression as argument:

⍎¯1∘⌽@(∊∘'+-×÷')

Execute the negative one step rotation ¯1∘⌽ done on @ members of the symbols set (∊∘'+-×÷').

\$\endgroup\$
6
\$\begingroup\$

Python 3.5, 118 113 164 bytes:

from re import*
def R(U):Z='(?<!\d)-\d+|\d+|[()]';O=sub(Z,'',U);print(eval(sub(Z,'%s',U).translate(str.maketrans(O,O[::-1])).replace('^','**')%tuple(findall(Z,U))))

A named function. Can probably be golfed down more. This will take quite a while and apparently plenty of memory to compute the solution for the input:

((22^22)+2*2^2^2^2*2-2+222222+22222*-2222-2*222*2*2+2^-2+(2+2+2+2+2)+222/222+2+22*2*2)*2*2*2

I started processing this with my program about 30 minutes ago as of the time of this edit (9:52 PM on July 27, 2016) and it is still going. EDIT: Well, it eventually started to take up too much memory, so I had to stop it at around 1 hour after I started, at around 10:52 PM on July 7, 2016.

EDIT # 2: Well, even for the updated last test case it's pretty much the same thing, as it takes quite a while for my program to start finding the answer before it eventually quits out on me with error code 137.

Try It Online for the Rest of the Test Cases! (Ideone)

\$\endgroup\$
  • \$\begingroup\$ Try with the new last test case; the old one had errors. \$\endgroup\$ – sintax Jul 29 '16 at 14:02
  • \$\begingroup\$ @sintax Yeah, the same issue still persists. :/ \$\endgroup\$ – R. Kap Jul 29 '16 at 18:04
3
\$\begingroup\$

Python 3, 195 bytes:

import re;I=input();x=[i for i in I if i in'+-*/^'];print(eval(''.join([i[0]+i[1]for i in[i for i in map(list,zip(*[[i for i in re.split('[+*/^-]',I)],x[-1:]+x[:-1]+['']]))]]).replace('^','**')))

Takes input on STDIN and leaves a number on STDOUT. I know that R. Kap already posted a Python answer, but the method I used is actually pretty interesting, so I thought I'll post this anyway.

The program first makes an the list: [chunks splitted by math chars, math chars rotated to the right]. It then transposes the array, flattens, converts to string, and evaluates.

\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES7), 154 bytes

f=
s=>[(s=s.replace(/(\(*-?\d+\)*)(.?)/g,(_,d,o)=>a.push(d)&&o,a=[])).slice(-1),...s.slice(0,-1)].map((o,i)=>a[i]+=o)&&eval(a.join` `.replace(/\^/g,'**'))
;
<input id=i placeholder=Input><input id=o placeholder=Output><input type=button value=Go onclick=o.value=f(i.value);>

Works by removing the values into a separate array so that the operators can be rotated.

\$\endgroup\$
  • \$\begingroup\$ What environment can I test this in? \$\endgroup\$ – Jordan Aug 5 '16 at 15:57
  • \$\begingroup\$ @Jordan I have converted my answer into a code snippet that can be tested in any ES7-compliant browser (not ES6 as previously inadvertently advertised). \$\endgroup\$ – Neil Aug 5 '16 at 17:22
  • \$\begingroup\$ Nice, you even got exponentiation to evaluate in the correct order (e.g., 2^3^2=512 rather than 64). \$\endgroup\$ – kamoroso94 Aug 13 '16 at 22:23
2
\$\begingroup\$

Matlab, 114 chars

Okay, so the last test case evaluates to Inf (once rotated, the expression 2^222222 appears...), but otherwise, all test cases hit.

Dealing with negatives, especially non-initial negatives, gave me fits.

i=input('');d=regexp(i(2:end),'[^\d|\)|\(]');d=d(~[0 d(2:end)-d(1:end-1)==1]);i(d+1)=i(1+d([end,1:end-1]));eval(i)

Inputs should be wrapped in single quotes (e.g., '2+3/5-(12*5)'), as per Matlab standard for string inputs.

Ungolfed and commented:

i=input('');                        # Get input from stdin.
d=regexp(i(2:end),'[^\d|\)|\(]');   # Find the positions of non-digit/paren characters
                                    # in the non-initial portion of the input.
d=d(~[0 d(2:end)-d(1:end-1)==1]);    # If there are consecutive operator-type characters,
                                    # assume the second is a negativity indicator and
                                    # delete its index from our list of operator indices.
i(d+1)=i(1+d([end,1:end-1]));       # Replace each non-initial operator character of the 
                                    # input with its own right-rotated operator from our
                                    # list of operator characters
eval(i)                             # Evaluate the string expression we just built.
\$\endgroup\$
  • \$\begingroup\$ I thought that would be assumed, from the nature of the language. I can add that. Also, yes, I mention at the top of my answer that the last test case eval's to Inf. The portion which reads '2*222222' and gets rotated to '2^222222' is too large for Matlab to store by a LOT. \$\endgroup\$ – sintax Jul 28 '16 at 16:18
  • 1
    \$\begingroup\$ Sorry, I hadn't seen that note \$\endgroup\$ – Luis Mendo Jul 28 '16 at 16:24
  • 1
    \$\begingroup\$ I'm pretty sure the example in that one case is flawed. Evaluating the rotation by hand gives 10959 + 2^888888 * 22222 which is a much larger number than is claimed. \$\endgroup\$ – sintax Jul 28 '16 at 16:29
  • \$\begingroup\$ @sintax Good catch! I have fixed that test case. The original test case had already been rotated once, so the second rotation threw it off. \$\endgroup\$ – NonlinearFruit Jul 28 '16 at 16:40
  • 1
    \$\begingroup\$ Trying with the new last test case gives me: i = '((22^22)+2*2^2^2^2*2-2+222222+22222*-2222-2*222*2*2+2^-2+(2+2+2+2+2)+222/222+2+22*2*2)*2*2*2', eval(i) = 2.7314e+30; After rotating i = '((22*22)^2+2*2^2^2^2*2-222222+22222+-2222*2-222*2*2*2+-2^(2+2+2+2+2)+222+222/2+22+2*2)*2*2*2', eval(i) = 227160. Does that seem right to you? \$\endgroup\$ – sintax Jul 28 '16 at 21:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.