Оцінювання виразів із числовими скороченнями


10

Ви працюєте в компанії, яка хоче зробити зручним для користувача калькулятор, і таким чином перед вами поставлено завдання додавати можливість користувачам використовувати "числові скорочення", тобто букви, що представляють числові значення, наприклад, kдля 1000. Оскільки ваша компанія хоче заощадити гроші на зберіганні в зазначених калькуляторах, ви повинні максимально скоротити код, щоб зменшити витрати на зберігання.


Ваше завдання

Ви повинні створити функцію, яка або зчитує вираз як вхід з STDIN, або приймає його як параметр і повертає його оцінку або друкує його в STDOUT.

Деякі роз'яснення

Дозвольте мені зробити деякі визначення. По-перше, у нас є вхід, який я називаю виразом. Це може бути щось на кшталт наступного:

x + y / z

У цьому виразі ми маємо три числа: x, y, і z, розділені оператори ( +і /). Ці числа не обов'язково є натуральними цілими числами (або навіть цілими числами). Що ускладнює речі, це коли ми повинні оцінювати скорочення, що містяться в числах. Наприклад, с

2k15

для цілей оцінки, ми розділили це на три числа: 2, 1000(що k), і 15. Потім, згідно з правилами, їх поєднуємо для отримання

2*1000 + 15 = 2015

Сподіваємось, це полегшує розуміння наступних правил.

Правила

Примітка: Якщо не вказано інше, ви можете інтерпретувати слово "числа" або його синоніми, включаючи скорочення.

  1. Нижче є числові Shorthands ваша функція повинна бути в змозі процесу: k, m, b, t, and e. k, m, b, and tвідповідають значенням 1000, 1000000, 1000000000, and 1000000000000відповідно (одна тисяча, мільйон, мільярд та один трильйон). Скорочення eзавжди буде супроводжуватися іншим номером n, і представляє 10^n. Ви повинні дозволити, щоб числові стенограми були присутніми nта були представлені раніше e. Наприклад, kekоцінює до 1000*10^1000.

  2. Для простоти, якщо число має в ньому скорочення e, воно буде використано лише один раз.

  3. Будь-яке число ( включене скорочення ) до скорочення на нього множиться. наприклад 120kk, буде оцінено як 120 * 1000 * 1000. Якщо перед ним немає числа, ви повинні припустити, що число дорівнює 1 (як, наприклад, в математиці ви могли б посилатися на змінну xнеявно як 1x). наприклад e10оцінює до 10^10. Інший приклад: 2m2kоцінює до 2*1000000*2*1000(до нього нічого не додано).

  4. До нього додається будь-яке число (скорочення не застосовується), що слідує за останньою стенограмою у номері, що містить стенограму. наприклад 2k12, буде оцінено як 2*1000 + 12. Виняток із цього випадку є, якщо використовується скорочення e, і в такому випадку число ( включене скорочення ) eбуде розглянуто як nі оцінено як 10^n(див. Перше правило).

  5. Ваша функція повинна вміти обробляти операторів, +, -, *, and /що складають відповідно, віднімання, множення та ділення відповідно. Це може обробити більше, якщо ви цього хочете.

  6. Операції оцінюються відповідно до порядку операцій.

  7. Числа у стенограмах - це не лише цілі числа. 3.5b1.2є дійсним і оцінюється як3.5*1000000000 + 1.2 = 3500000001.2

  8. Вбудовані модулі не дозволяються, якщо вони існують для подібних речей. Виняток, який я додам, буде, якщо ваша мова автоматично перетворює велику кількість на наукові позначення, і в цьому випадку це допустимо для ваших результатів.

  9. Найкоротший код у байтах виграє, застосовуючи стандартні лазівки.

Вхідні дані

Вхід буде виразом з кожним числом та оператором, розділеним пробілами. Цифри можуть містити або не містити скорочення. Зразок показаний нижче:

10 + 1b - 2k

Вихідні дані

Ваша функція повинна виводити оцінку виразу як числа. Допустимо використовувати наукові позначення, якщо вихід буде занадто великим для відображення. У вас повинно бути не менше трьох знаків після коми, якщо число не є цілим числом. Це допустимо, якщо ви зберігаєте ці десяткові знаки, якщо число є цілим числом.

Випробування

Вхідні дані

t

Вихідні дані

1000000000000

Вхідні дані

1 + 4b / 10k11

Вихідні дані

399561.483

Вхідні дані

e2 + k2ke-1 - b12

Вихідні дані

-999799912

або

-999799912.000

Вхідні дані

142ek12

Вихідні дані

142e1012

або

142.000e1012

Вхід:

1.2m5.25

Вихід:

1200005.25

Заключні ноти

Це мій перший виклик, розміщений (за деякою допомогою користувачів на пісочниці). Якщо щось незрозуміле, дайте мені це знати, і я зроблю все можливе, щоб уточнити.


1
Хороший перший виклик
Digital Trauma

@DigitalTrauma Дякую велике! Я з нетерпінням чекаю відповідей.
коул

Я не розумію другого прикладу. Я вважав, що середній термін трактується як 1000 + 2000 * 10 ^ -1, але це дало остаточну відповідь -999998712. (Крім того, моя інтерпретація, схоже, не узгоджується з " останньою стенограмою " правила 4 , але я не впевнений, як інакше зрозуміти послідовність k2k.) Чи можете ви пояснити, будь ласка, кроки в її оцінці?
DLosc

@trichoplax так, це повинно бути лише число; хороший улов.
Коул

1
Подивившись на коментарі пісочниці поста, я думаю , що приклад , як 2m2kмає бути додані до обговорення правила 3. Крім того , було б краще використовувати інший термін - можливо , «ціле» - для буквальних чисел , як , 123що не є скороченими. Слово "число" має тут приблизно 3 різних визначення, як це є зараз.
DLosc

Відповіді:


4

Python 2, 553 байт

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

Це запитання виглядало трохи нелюбимим і здавалося веселим, тому я дав йому постріл. Я ніколи раніше не робив кодовий гольф, тому, мабуть, багато чого можна вдосконалити, але я дав все можливе, виходячи з моїх знань мови. Еквівалентне рішення можливе в Python 3 ціною одного додаткового байта: print repr(z[0])-> print(repr(z[0])).

Використання - це щось, що відповідає лінії

python2 ShorthandMath.py <equation>

тобто

python2 ShorthandMath.py e2 + k2ke-1 - b12

виходи

-999799912.0

Інформація про те, як це покращити, буде дуже вдячна. Якщо є достатній інтерес, я можу зняти гольф і прокоментувати програму, але більшість її вже досить розбірлива (факт, що стосується коду гольфу).

Слід зазначити, що програма розбивається на прикладі, 142ek12оскільки це значення смішно велике і програма переповнює.

Для компенсації, наступне трохи довше, але теоретично може обробити все, що кидається на нього завдяки використанню вбудованої бібліотеки довільної точності. Синтаксис тотожний.

Python 2, 589 588 байт (довільна точність)

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]

Я збираюся сказати, що перша версія повинна бути добре, і я повернуся до вас, якщо спробуйте щось не так (я зараз не можу подивитися / думати занадто уважно).
Коул

@Cole Awesome, спасибі Я спробував це на кожному наведеному прикладі, і він отримує всі потрібні принаймні.
BobChao87
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.