Evaluación de expresiones con shorthands numéricos

10

Trabaja para una empresa que quiere hacer una calculadora fácil de usar y, por lo tanto, se le ha encomendado la tarea de agregar la capacidad para que los usuarios usen "shorthands numéricos", es decir, letras que representan valores numéricos, como kfor 1000. Debido a que su empresa quiere ahorrar dinero en almacenamiento en dichas calculadoras, debe minimizar su código tanto como sea posible para reducir el costo de almacenamiento.


Tu tarea

Debe crear una función que lea una expresión como entrada de STDIN o la tome como parámetro y devuelva su evaluación o la imprima en STDOUT.

Alguna aclaración

Déjame hacer algunas definiciones. En primer lugar, tenemos la entrada, que llamo una expresión. Esto puede ser algo como lo siguiente:

x + y / z

Dentro de esta expresión tenemos tres números: x, yy z, separados por los operadores ( +y /). Estos números no son necesariamente enteros positivos (o incluso enteros). Lo que complica las cosas es cuando tenemos que evaluar las manos cortas contenidas dentro de los números. Por ejemplo, con

2k15

para fines de evaluación, dividimos esta en tres números: 2, 1000(que es k), y 15. Luego, de acuerdo con las reglas, las combinamos para obtener

2*1000 + 15 = 2015

Esperemos que esto facilite un poco la comprensión de las siguientes reglas.

Reglas

NB A menos que se especifique lo contrario, puede interpretar la palabra "números" o sus sinónimos para incluir shorthands.

  1. El siguiente constituye las abreviaturas numéricos que su función debe ser capaz de proceso: k, m, b, t, and e. k, m, b, and tcorresponden a los valores 1000, 1000000, 1000000000, and 1000000000000respectivamente (mil, un millón, mil millones y un billón). La etaquigrafía siempre será seguida por otro número n, y representa 10^n. Debe permitir que las shorthands numéricas estén presentes ny presentes antes e. Por ejemplo, kekevalúa a 1000*10^1000.

  2. En aras de la simplicidad, si un número tiene la taquigrafía e, solo se usará una vez.

  3. Cualquier número ( incluido shorthands ) antes de que una taquigrafía se multiplique por ella. por ejemplo 120kk, se evaluaría como 120 * 1000 * 1000. Si no hay un número antes, debe suponer que el número es 1 (como, en matemáticas, podría tratar una variable ximplícitamente como 1x). ej. e10evalúa a 10^10. Otro ejemplo: 2m2kevalúa a 2*1000000*2*1000(no se le agrega nada).

  4. Se le agrega cualquier número (no se aplican las abreviaturas ) después de la última taquigrafía en un número que contiene una taquigrafía. por ejemplo 2k12, se evaluaría como 2*1000 + 12. La excepción a esto es si ese usa la taquigrafía , en cuyo caso el número ( incluidas las abreviaturas ) ese tratará ny evaluará como 10^n(ver la primera regla).

  5. Su función debe poder procesar los operadores +, -, *, and /que son suma, resta, multiplicación y división respectivamente. Puede procesar más, si así lo desea.

  6. Las operaciones se evalúan de acuerdo con el orden de las operaciones.

  7. Los números en las manos cortas no son solo enteros. 3.5b1.2es válido y debe evaluarse como3.5*1000000000 + 1.2 = 3500000001.2

  8. Las incorporadas no están permitidas, si existen para este tipo de cosas. La excepción que agregaré sería si su idioma convierte automáticamente grandes números a notación científica, en cuyo caso eso es admisible para su salida.

  9. El código más corto en bytes gana, aplicando lagunas estándar.

Entrada

La entrada será una expresión con cada número y operador separados por espacios. Los números pueden o no contener una taquigrafía. A continuación se muestra una muestra:

10 + 1b - 2k

Salida

Su función debe generar la evaluación de la expresión como un número. Es admisible utilizar notación científica si la salida sería demasiado grande para mostrar. Debe tener al menos tres decimales si el número no es un entero. Es admisible si conserva estos lugares decimales si el número es un entero.

Casos de prueba

Entrada

t

Salida

1000000000000

Entrada

1 + 4b / 10k11

Salida

399561.483

Entrada

e2 + k2ke-1 - b12

Salida

-999799912

o

-999799912.000

Entrada

142ek12

Salida

142e1012

o

142.000e1012

Entrada:

1.2m5.25

Salida:

1200005.25

Notas finales

Este es mi primer desafío publicado (con algo de ayuda de los usuarios en el sandbox). Si algo no está claro, hágamelo saber y haré todo lo posible para aclararlo.

col
fuente
1
Buen primer desafío
Trauma digital
@ DigitalTrauma ¡Muchas gracias! Espero ver las respuestas.
cole
No entiendo el segundo ejemplo. Pensé que el término medio se interpretaba como 1000 + 2000 * 10 ^ -1, pero eso dio una respuesta final de -999998712. (Además, mi interpretación no parece coincidir con la " última taquigrafía " de la regla 4 , pero no estoy seguro de qué otra manera entender la secuencia k2k). ¿Puede explicar los pasos para evaluarla?
DLosc
@trichoplax sí, solo debería ser un número; buena atrapada.
cole
1
Después de mirar los comentarios en la publicación de sandbox, creo que 2m2kdebería agregarse un ejemplo similar a la discusión de la regla 3. Además, podría ser mejor usar un término diferente, tal vez "entero", para los números literales como 123ese No son shorthands. La palabra "número" tiene alrededor de 3 definiciones diferentes aquí, tal como está ahora.
DLosc

Respuestas:

4

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])

Esta pregunta parecía poco amada y parecía divertida, así que le di una oportunidad. Nunca antes había practicado golf de código, por lo que probablemente haya muchas cosas que puedan mejorarse, pero di lo mejor de mí en función de mi conocimiento del idioma. Es posible una solución equivalente en Python 3 a costa de un byte adicional: print repr(z[0])-> print(repr(z[0])).

El uso es algo similar a

python2 ShorthandMath.py <equation>

es decir

python2 ShorthandMath.py e2 + k2ke-1 - b12

salidas

-999799912.0

Se agradecería mucho la información sobre cómo mejorar esto. Si hay suficiente interés, puedo eliminar el golf y comentar el programa, pero la mayoría ya es bastante legible (un hecho preocupante en el código de golf).

Cabe señalar que el programa rompe con el ejemplo 142ek12porque ese valor es ridículamente grande y el programa se desborda.

Para compensar, lo siguiente es un poco más largo, pero en teoría puede manejar cualquier cosa que se le arroje debido al uso de la biblioteca de precisión arbitraria incorporada. La sintaxis es idéntica.

Python 2, 589 588 bytes (precisión arbitraria)

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]
BobChao87
fuente
Voy a decir que la primera versión debería estar bien y me pondré en contacto con usted si intento que haya algo mal (no puedo mirar / pensar con mucho cuidado en este momento).
cole
@Cole Awesome, gracias. Lo probé en todos los ejemplos que se dan, y al menos todos los hacen bien.
BobChao87