Avaliando expressões com atalhos numéricos

10

Você trabalha para uma empresa que deseja criar uma calculadora fácil de usar e, portanto, recebeu a tarefa de adicionar a capacidade de os usuários usarem "atalhos numéricos", ou seja, letras que representam valores numéricos, como kpara 1000. Como sua empresa deseja economizar dinheiro com armazenamento nessas calculadoras, você deve minimizar seu código o máximo possível para reduzir o custo de armazenamento.


Sua tarefa

Você deve criar uma função que leia uma expressão como entrada de STDIN ou a aceite como parâmetro e retorne sua avaliação ou imprima em STDOUT.

Alguns esclarecimentos

Deixe-me fazer algumas definições. Primeiro, temos a entrada, que eu chamo de expressão. Isso pode ser algo como o seguinte:

x + y / z

Dentro desta expressão que têm três números: x, y, e z, separados por operadores ( +e /). Esses números não são necessariamente números inteiros positivos (ou mesmo números inteiros). O que complica as coisas é quando temos que avaliar taquigrafia contidas em números. Por exemplo, com

2k15

Para fins de avaliação, nós dividir este em três números: 2, 1000(que é k), e 15. Então, de acordo com as regras, nós as combinamos para obter

2*1000 + 15 = 2015

Esperamos que isso facilite um pouco a compreensão das seguintes regras.

Regras

Nota: Salvo especificação em contrário, você pode interpretar a palavra "números" ou seus sinônimos para incluir letras abreviadas.

  1. O seguinte constitui os atalhos numéricos a sua função deve ser capaz de processar: k, m, b, t, and e. k, m, b, and tcorrespondem aos valores 1000, 1000000, 1000000000, and 1000000000000respectivamente (mil, um milhão, um bilhão e um trilhão). A eabreviação será sempre seguida por outro número n, e representa 10^n. Você deve permitir que atalhos numéricos estejam presentes ne apresentem antes e. Por exemplo, kekavalia como 1000*10^1000.

  2. Por uma questão de simplicidade, se um número tiver uma abreviação e, ele será usado apenas uma vez.

  3. Qualquer número ( taquigrafia incluído ) antes de uma taquigrafia ser multiplicada por ele. por exemplo, 120kkseria avaliado como 120 * 1000 * 1000. Se não houver um número antes dele, você deve assumir que o número é 1 (como, em matemática, você pode tratar ximplicitamente uma variável como 1x). por exemplo, e10avalia para 10^10. Outro exemplo: 2m2kavalia para 2*1000000*2*1000(nada é adicionado a ele).

  4. Qualquer número (atalhos não se aplica) após o último atalho em um número que contenha um atalho é adicionado a ele. por exemplo, 2k12seria avaliado como 2*1000 + 12. A exceção é se a abreviação efor usada. Nesse caso, o número ( abreviação incluído ) a seguir eserá tratado ne avaliado como 10^n(consulte a primeira regra).

  5. Sua função deve ser capaz de processar os operadores +, -, *, and /que são adição, subtração, multiplicação e divisão, respectivamente. Pode processar mais, se você desejar.

  6. As operações são avaliadas de acordo com a ordem das operações.

  7. Os números em taquigrafia não são apenas números inteiros. 3.5b1.2é válido e deve ser avaliado como3.5*1000000000 + 1.2 = 3500000001.2

  8. Built-ins não são permitidos, se existirem para esse tipo de coisa. A exceção que adicionarei seria se seu idioma converter automaticamente grandes números em notação científica; nesse caso, isso é admissível para sua saída.

  9. O menor código em bytes vence, aplicando brechas padrão.

Entrada

A entrada será uma expressão com cada número e operador separados por espaços. Os números podem ou não conter uma abreviação. Uma amostra é mostrada abaixo:

10 + 1b - 2k

Resultado

Sua função deve gerar a avaliação da expressão como um número. É admissível usar notação científica se a saída for muito grande para ser exibida. Você deve ter pelo menos três casas decimais se o número não for um número inteiro. É admissível se você reter essas casas decimais se o número for um número inteiro.

Casos de teste

Entrada

t

Resultado

1000000000000

Entrada

1 + 4b / 10k11

Resultado

399561.483

Entrada

e2 + k2ke-1 - b12

Resultado

-999799912

ou

-999799912.000

Entrada

142ek12

Resultado

142e1012

ou

142.000e1012

Entrada:

1.2m5.25

Resultado:

1200005.25

Notas Finais

Este é o meu primeiro desafio publicado (com alguma ajuda dos usuários na caixa de areia). Se algo não estiver claro, informe-me e farei o possível para esclarecer.

Cole
fonte
11
Bom primeiro desafio
Digital Trauma
@DigitalTrauma Muito obrigado! Estou ansioso para ver as respostas.
cole
Eu não entendo o segundo exemplo. Eu pensei que o termo do meio fosse interpretado como 1000 + 2000 * 10 ^ -1, mas isso deu uma resposta final de -999998712. (Além disso, minha interpretação não parece concordar com a " última abreviação " da regra 4. , mas não tenho certeza de como entender a sequência k2k.) Você pode explicar as etapas de avaliação?
DLosc
@trichoplax sim, deve ser apenas um número; boa pegada.
cole
11
Depois de examinar os comentários na postagem da sandbox, acho que um exemplo como 2m2kdeve ser adicionado à discussão da regra 3. Além disso, talvez seja melhor usar um termo diferente - talvez "número inteiro" - para números literais como 123esse não são taquigrafia. A palavra "número" tem cerca de 3 definições diferentes aqui, como está agora.
DLosc

Respostas:

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

Essa pergunta parecia um pouco mal amada e divertida, então eu tentei. Eu nunca fiz golfe com código antes, então provavelmente há muito que pode ser melhorado, mas dei o melhor de mim com base no meu conhecimento do idioma. Uma solução equivalente é possível no Python 3 ao custo de um byte extra: print repr(z[0])-> print(repr(z[0])).

O uso é algo parecido com o

python2 ShorthandMath.py <equation>

ie

python2 ShorthandMath.py e2 + k2ke-1 - b12

saídas

-999799912.0

A contribuição de como melhorar isso seria muito apreciada. Se houver interesse suficiente, posso desdobrar e comentar o programa, mas a maioria já é bastante legível (um fato preocupante no código de golfe).

Deve-se notar que o programa quebra com o exemplo 142ek12porque esse valor é ridiculamente grande e o programa transborda.

Para compensar, o seguinte é um pouco mais longo, mas teoricamente pode lidar com qualquer coisa lançada devido ao uso da biblioteca de precisão arbitrária incorporada. A sintaxe é idêntica.

Python 2, 589 588 bytes (precisão arbitrária)

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
fonte
Eu vou dizer que a primeira versão deve estar bem e eu voltarei para você se tentar algo errado (não posso olhar / pensar com muito cuidado agora).
cole
@ Cole impressionante, obrigado. Eu tentei em todos os exemplos, e isso acerta todos eles pelo menos.
21815 BobChao87 #