10
\$\begingroup\$

You work for a company that wants to make a user-friendly calculator, and thus you have been tasked with adding the ability for users to use "numerical shorthands," that is, letters that represent numerical values, such as k for 1000. Because your company wants to save money on storage in said calculators, you must minimize your code as much as possible to reduce the cost of storage.


Your Task

You are to create a function that either reads an expression as input from STDIN or takes it as a parameter and returns its evaluation or prints it to STDOUT.

Some Clarification

Let me do some definitions. First off, we have the input, which I call an expression. This can be something like the following:

x + y / z

Within this expression we have three numbers: x, y, and z, separated by operators (+ and /). These numbers are not necessarily positive integers (or even integers). What complicates things is when we have to evaluate shorthands contained within numbers. For example, with

2k15

for purposes of evaluation, we split this up into three numbers: 2, 1000 (which is k), and 15. Then, according to the rules, we combine them to obtain

2*1000 + 15 = 2015

Hopefully this makes it a bit easier to understand the following rules.

Rules

N.B. Unless specified otherwise, you can interpret the word "numbers" or its synonyms to include shorthands.

  1. The following constitutes the numerical shorthands your function must be able to process: k, m, b, t, and e. k, m, b, and t correspond to the values 1000, 1000000, 1000000000, and 1000000000000 respectively (one thousand, one million, one billion, and one trillion). The e shorthand will always be followed by another number, n, and represents 10^n. You must allow for numerical shorthands to be present in n and present before e. For example, kek evaluates to 1000*10^1000.

  2. For simplicity's sake, if a number has the shorthand e in it, it will only be used once.

  3. Any number (shorthands included) before a shorthand is multiplied by it. e.g. 120kk would be evaluated as 120 * 1000 * 1000. If there is no number before it, you must assume that the number is 1 (like how you might, in mathematics, treat a variable x implicitly as 1x). e.g. e10 evaluates to 10^10. Another example: 2m2k evaluates to 2*1000000*2*1000 (nothing is added to it).

  4. Any number (shorthands do not apply) following the last shorthand in a number containing a shorthand is added to it. e.g. 2k12 would be evaluated as 2*1000 + 12. The exception to this is if the shorthand e is used, in which case the number (shorthands included) following e will be treated as n and evaluated as 10^n (see the first rule).

  5. Your function must be able to process the operators +, -, *, and / which are addition, subtraction, multiplication, and division respectively. It may process more, if you so desire.

  6. Operations are evaluated according to the order of operations.

  7. Numbers in shorthands are not only integers. 3.5b1.2 is valid and is to be evaluated as 3.5*1000000000 + 1.2 = 3500000001.2

  8. Built-ins are not allowed, if they exist for this sort of thing. The exception that I'll add would be if your language automatically converts large numbers to scientific notation, in which case that is admissible for your output.

  9. Shortest code in bytes wins, standard loopholes applying.

Input

The input will be an expression with each number and operator separated by spaces. Numbers may or may not contain a shorthand. A sample is shown below:

10 + 1b - 2k

Output

Your function must output the evaluation of the expression as a number. It is admissible to use scientific notation if the output would be too large to display. You must have at least three decimal places if the number is not an integer. It is admissible if you retain these decimal places if the number is an integer.

Test Cases

Input

t

Output

1000000000000

Input

1 + 4b / 10k11

Output

399561.483

Input

e2 + k2ke-1 - b12

Output

-999799912

or

-999799912.000

Input

142ek12

Output

142e1012

or

142.000e1012

Input:

1.2m5.25

Output:

1200005.25

Final Notes

This is my first challenge posted (with some help from users on the sandbox). If anything is unclear, make it known to me and I will do my best to clarify.

\$\endgroup\$
  • 1
    \$\begingroup\$ Good first challenge \$\endgroup\$ – Digital Trauma Sep 10 '15 at 23:20
  • \$\begingroup\$ @DigitalTrauma Thanks a lot! I look forward to seeing the answers. \$\endgroup\$ – cole Sep 10 '15 at 23:22
  • \$\begingroup\$ I don't understand the second example. I thought the middle term was interpreted as 1000 + 2000 * 10 ^ -1, but that gave a final answer of -999998712. (Also, my interpretation doesn't seem to jive with rule 4's "last shorthand," but I'm not sure how else to understand the sequence k2k.) Can you please explain the steps in evaluating it? \$\endgroup\$ – DLosc Sep 10 '15 at 23:22
  • \$\begingroup\$ @trichoplax yes, it should only be a number; good catch. \$\endgroup\$ – cole Sep 10 '15 at 23:24
  • 1
    \$\begingroup\$ After looking at the comments on the sandbox post, I think an example like 2m2k should be added to the discussion of rule 3. Also, it might be best to use a different term--maybe "integer"--for the literal numbers like 123 that are not shorthands. The word "number" has about 3 different definitions here, as it stands now. \$\endgroup\$ – DLosc Sep 11 '15 at 0:15
4
\$\begingroup\$

Python 2, 553 bytes

import sys
a=lambda i:lambda j:j*10**i
d={'k':a(3),'m':a(6),'b':a(9),'t':a(12)}
e='e'
o={'+':lambda i,j:i+j,'-':lambda i,j:i-j,'*':lambda i,j:i*j,'/':lambda i,j:i/j,e:lambda i,j:i*10**j}
r=[e,'*','/','+','-']
x=0
y=k=b=''
z=[]
q=lambda i,j:float(i or j)
for l in ''.join(sys.argv[1:]):
 if l in d:x,y=d[l](q(x,1)*q(y,1)),b
 elif l==e:z.extend([q(x+q(y,0),1),l]);x,y=0,b
 elif k==e:y+=l
 elif l in o:z.extend([x+q(y,0),l]);x,y=0,b
 else:y+=l
 k=l
z.append(x+q(y,0))
for m in r:
 while m in z:n=z.index(m);z[n-1:n+2]=[o[m](z[n-1],z[n+1])]
print repr(z[0])

This question looked a little unloved and seemed fun, so I gave it a shot. I've never done code golf before, so there's probably a lot that can be improved, but I gave it my best based on my knowledge of the language. An equivalent solution is possible in Python 3 at the cost of one extra byte: print repr(z[0]) -> print(repr(z[0])).

Usage is something along the lines of

python2 ShorthandMath.py <equation>

i.e.

python2 ShorthandMath.py e2 + k2ke-1 - b12

outputs

-999799912.0

Input for how to improve this would be much appreciated. If there is sufficient interest, I can ungolf and comment the program, but most of it pretty legible already (a concerning fact in code golf).

It should be noted that the program breaks with the example 142ek12 because that value is ludicrously large and the program overflows.

To compensate, the following is slightly longer, but can theoretically handle anything thrown at it due to use of the built in arbitrary precision library. Syntax is identical.

Python 2, 589 588 bytes (arbitrary precision)

import sys
from decimal import*
a=lambda i:lambda j:j*10**i
d={'k':a(3),'m':a(6),'b':a(9),'t':a(12)}
e='e'
o={'+':lambda i,j:i+j,'-':lambda i,j:i-j,'*':lambda i,j:i*j,'/':lambda i,j:i/j,e:lambda i,j:i*10**j}
r=[e,'*','/','+','-']
x=c=Decimal(0)
y=k=b=''
z=[]
q=lambda i,j:Decimal(float(i or j))
for l in ''.join(sys.argv[1:]):
 if l in d:x,y=d[l](q(x,1)*q(y,1)),b
 elif l==e:z.extend([q(x+q(y,0),1),l]);x,y=c,b
 elif k==e:y+=l
 elif l in o:z.extend([x+q(y,0),l]);x,y=c,b
 else:y+=l
 k=l
z.append(x+q(y,0))
for m in r:
 while m in z:n=z.index(m);z[n-1:n+2]=[o[m](z[n-1],z[n+1])]
print z[0]
\$\endgroup\$
  • \$\begingroup\$ I'm going to say the first version should be fine and I'll get back to you if try there's anything wrong (I can't look/think too carefully right now). \$\endgroup\$ – cole Oct 13 '15 at 1:15
  • \$\begingroup\$ @Cole Awesome, thanks. I tried it out on every example given, and it gets all of those right at least. \$\endgroup\$ – BobChao87 Oct 13 '15 at 5:44

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.