Оценка выражений с помощью числовых сокращений


10

Вы работаете в компании, которая хочет создать удобный для пользователя калькулятор, и поэтому вам было поручено добавить пользователям возможность использовать «числовые сокращения», то есть буквы, которые представляют числовые значения, например, kдля 1000. Поскольку ваша компания хочет сэкономить на хранении в указанных калькуляторах, вы должны максимально сократить код, чтобы снизить стоимость хранения.


Твое задание

Вы должны создать функцию, которая либо считывает выражение как входные данные из STDIN, либо принимает его в качестве параметра и возвращает его оценку, либо печатает его в STDOUT.

Некоторые разъяснения

Позвольте мне сделать некоторые определения. Во-первых, у нас есть вход, который я называю выражением. Это может быть что-то вроде следующего:

x + y / z

В этом выражении мы имеем три числа: x, y, и z, разделенные операторы ( +и /). Эти числа не обязательно являются положительными целыми числами (или даже целыми числами). Что усложняет ситуацию, так это когда нам приходится оценивать сокращения, содержащиеся в числах. Например, с

2k15

для целей оценки, мы разделили это на три числа: 2, 1000(что k), и 15. Затем, согласно правилам, мы объединяем их для получения

2*1000 + 15 = 2015

Надеюсь, это немного облегчает понимание следующих правил.

правила

NB. Если не указано иное, слово «числа» или его синонимы можно интерпретировать как включающие сокращения.

  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
Хороший первый вызов
цифровая травма

@DigitalTrauma Большое спасибо! Я с нетерпением жду ответов.
Коул

Я не понимаю второй пример. Я думал, что средний термин был истолкован как 1000 + 2000 * 10 ^ -1, но это дало окончательный ответ -999998712. (Кроме того, моя интерпретация, похоже, не совпадает с « последним условным обозначением» правила 4 , но я не уверен, как еще понять последовательность k2k.) Не могли бы вы объяснить шаги при ее оценке?
DLosc 10.09.15

@trichoplax да, это должен быть только номер; хороший улов.
Коул

1
Посмотрев на комментарии к сообщению о песочнице, я думаю, что пример вроде 2m2kдолжен быть добавлен к обсуждению правила 3. Кроме того, может быть лучше использовать другой термин - возможно, "целое число" - для таких литеральных чисел, как 123этот являются не Shorthands. Слово «число» имеет здесь около 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]

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

@ Кол, Круто, спасибо. Я опробовал его на каждом приведенном примере, и он, по крайней мере, все правильно понял.
BobChao87
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.