Ocena wyrażeń za pomocą skrótów numerycznych

10

Pracujesz dla firmy, która chce stworzyć przyjazny dla użytkownika kalkulator, dlatego też powierzono ci zadanie dodania możliwości używania przez użytkowników „skrótów numerycznych”, czyli liter reprezentujących wartości liczbowe, na przykład kdla 1000. Ponieważ Twoja firma chce zaoszczędzić pieniądze na przechowywaniu we wspomnianych kalkulatorach, musisz maksymalnie zminimalizować swój kod, aby zmniejszyć koszty przechowywania.


Twoje zadanie

Masz utworzyć funkcję, która albo odczytuje wyrażenie jako dane wejściowe z STDIN, albo przyjmuje je jako parametr i zwraca jego ocenę lub drukuje je do STDOUT.

Trochę wyjaśnienia

Pozwól mi zrobić kilka definicji. Po pierwsze, mamy dane wejściowe, które nazywam wyrażeniem. Może to być coś takiego:

x + y / z

W ramach tej wypowiedzi mamy trzy liczby: x, y, i z, oddzielone przez operatorów ( +i /). Liczby te niekoniecznie są dodatnimi liczbami całkowitymi (lub nawet liczbami całkowitymi). To, co komplikuje sytuację, to konieczność oceny skrótów zawartych w liczbach. Na przykład za pomocą

2k15

dla celów oceny, możemy podzielić to na trzy numery: 2, 1000(co jest k), i 15. Następnie, zgodnie z zasadami, łączymy je, aby uzyskać

2*1000 + 15 = 2015

Mamy nadzieję, że dzięki temu nieco łatwiej jest zrozumieć następujące zasady.

Zasady

NB O ile nie określono inaczej, można interpretować słowo „liczby” lub jego synonimy w celu uwzględnienia skrótów.

  1. Poniższa stanowi numeryczne shorthands czynność musi być w stanie procesu: k, m, b, t, and e. k, m, b, and todpowiadają 1000, 1000000, 1000000000, and 1000000000000odpowiednio wartościom (tysiąc, jeden milion, jeden miliard i jeden bilion). Po eskrócie zawsze będzie następowała inna liczba n, i reprezentuje 10^n. Musisz pozwolić, aby stenografia numeryczna była obecna ni obecna wcześniej e. Na przykład kekocenia na 1000*10^1000.

  2. Dla uproszczenia, jeśli liczba zawiera skrót e, zostanie użyta tylko raz.

  3. Dowolna liczba ( łącznie ze skrótami ) przed skrótem jest przez nią mnożona. np. 120kkzostanie oceniony jako 120 * 1000 * 1000. Jeśli nie ma przed nim żadnej liczby, musisz założyć, że liczba wynosi 1 (podobnie jak w matematyce możesz traktować zmienną xdomyślnie jako 1x). np. e10ocenia na 10^10. Kolejny przykład: 2m2kocenia na 2*1000000*2*1000(nic nie jest do niego dodawane).

  4. Dodaje się do niej dowolną liczbę (skróty nie mają zastosowania) po ostatnim skrócie w liczbie zawierającej skróty. np. 2k12zostanie oceniony jako 2*1000 + 12. Wyjątkiem jest sytuacja e, w której stosuje się skrót , w którym to przypadku liczba (wraz ze skrótami ) ebędzie traktowana jako ni oceniana jako 10^n(patrz pierwsza reguła).

  5. Twoja funkcja musi być w stanie przetwarzać operatory, +, -, *, and /które odpowiednio dodają, odejmują, mnożą i dzielą. Jeśli chcesz, może przetwarzać więcej.

  6. Operacje są oceniane zgodnie z kolejnością operacji.

  7. Liczby w skrótach to nie tylko liczby całkowite. 3.5b1.2jest ważny i należy go oceniać jako3.5*1000000000 + 1.2 = 3500000001.2

  8. Wbudowane nie są dozwolone, jeśli istnieją dla tego rodzaju rzeczy. Wyjątkiem, który dodam, byłoby, gdyby Twój język automatycznie konwertuje duże liczby na notację naukową, w którym to przypadku jest to dopuszczalne dla twoich wyników.

  9. Najkrótszy kod w bajtach wygrywa, obowiązują standardowe luki.

Wejście

Dane wejściowe będą wyrażeniem z każdą liczbą i operatorem oddzielonymi spacjami. Liczby mogą zawierać skrót lub nie. Przykład pokazano poniżej:

10 + 1b - 2k

Wynik

Twoja funkcja musi wyświetlać ocenę wyrażenia jako liczbę. Dopuszczalne jest stosowanie notacji naukowej, jeśli wynik byłby zbyt duży do wyświetlenia. Musisz mieć co najmniej trzy miejsca po przecinku, jeśli liczba nie jest liczbą całkowitą. Dopuszczalne jest zachowanie tych miejsc dziesiętnych, jeśli liczba jest liczbą całkowitą.

Przypadki testowe

Wejście

t

Wynik

1000000000000

Wejście

1 + 4b / 10k11

Wynik

399561.483

Wejście

e2 + k2ke-1 - b12

Wynik

-999799912

lub

-999799912.000

Wejście

142ek12

Wynik

142e1012

lub

142.000e1012

Wejście:

1.2m5.25

Wynik:

1200005.25

Uwagi końcowe

To jest moje pierwsze opublikowane wyzwanie (z pewną pomocą użytkowników w piaskownicy). Jeśli coś jest niejasne, daj mi znać, a ja postaram się wyjaśnić.

kapusta
źródło
1
Dobre pierwsze wyzwanie
Digital Trauma
@DigitalTrauma Dziękuję bardzo! Nie mogę się doczekać odpowiedzi.
cole,
Nie rozumiem drugiego przykładu. Myślałem, że termin średni został zinterpretowany jako 1000 + 2000 * 10 ^ -1, ale to dało ostateczną odpowiedź na -999998712. (Poza tym moja interpretacja nie wydaje się mieszać z „ ostatnią stenografią ” z reguły 4 , ale nie jestem pewien, jak inaczej zrozumieć sekwencję k2k.) Czy możesz wyjaśnić kroki w jej ocenie?
DLosc
@trichoplax tak, powinna to być tylko liczba; dobry chwyt.
cole,
1
Po zapoznaniu się z uwagami na stanowisku piaskownicy, myślę przykładem jak 2m2kpowinna być dodana do dyskusji rządów 3. Ponadto, może być najlepiej użyć innego terminu - może „całkowitą” - dla dosłowne numery jak 123to nie są stenografiami. Słowo „liczba” ma w tej chwili około 3 różnych definicji.
DLosc

Odpowiedzi:

4

Python 2, 553 bajtów

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

To pytanie wyglądało trochę niekochane i wydawało się zabawne, więc spróbowałem. Nigdy wcześniej nie grałem w golfa kodowego, więc prawdopodobnie jest wiele rzeczy, które można poprawić, ale dałem z siebie wszystko w oparciu o moją znajomość języka. W Pythonie 3 możliwe jest równoważne rozwiązanie kosztem jednego dodatkowego bajtu: print repr(z[0])-> print(repr(z[0])).

Użycie jest czymś podobnym do

python2 ShorthandMath.py <equation>

to znaczy

python2 ShorthandMath.py e2 + k2ke-1 - b12

wyjścia

-999799912.0

Doceniony zostanie wkład w to, jak to poprawić. Jeśli jest wystarczające zainteresowanie, mogę odhaczyć i skomentować program, ale większość z nich jest już dość czytelna (niepokojący fakt w golfie kodowym).

Należy zauważyć, że program zrywa z przykładem, 142ek12ponieważ ta wartość jest absurdalnie duża, a program się przepełnia.

Aby to zrekompensować, poniższe są nieco dłuższe, ale teoretycznie mogą obsłużyć wszystko, co zostanie na nie rzucone, dzięki zastosowaniu wbudowanej biblioteki o dowolnej precyzji. Składnia jest identyczna.

Python 2, 589 588 bajtów (dowolna precyzja)

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
źródło
Powiem, że pierwsza wersja powinna być w porządku i skontaktuję się z Tobą, jeśli spróbuję coś złego (nie mogę teraz patrzeć / myśleć zbyt ostrożnie).
cole
@Cole Awesome, dzięki. Wypróbowałem to na każdym podanym przykładzie i wszystko to działa poprawnie.
BobChao87,