Счет за воду Фреда


9

Фред квазидружественный парень, но на самом деле он подлый.

Из-за этого Фред живет один в маленькой квартире в Лос-Альтос, штат Калифорния. Фред такой подлый, потому что он очень требователен к воде. Поэтому он нуждается в вашей помощи, чтобы выяснить, какой у него счет за воду.

Ваша задача - написать функцию или программу, которая возвращает счет за воду, учитывая количество воды, используемой в качестве входных данных (которое всегда является целым числом).

Потребление воды происходит по уровням. Это означает, что существуют диапазоны цен в зависимости от количества воды.

Это уровни, их цены и количество воды, которое они соответствуют:

Tier I
   First 10 Ccf: $3.8476/Ccf
Tier II
   Next 17 Ccf: $4.0932/Ccf
Tier III
   All subsequent water: $4.9118/Ccf

Для n сотен кубических футов (Ccf) также предусмотрены следующие дополнительные расходы:

CPUC fee: 1.5% of above charges
LIRA quantity surcharge: $0.047*n
PBOP amoritization surcharge: $0.004*n

Сумма сборов уровня I, уровня II, уровня III, CPUC, LIRA и PBOP представляет собой общий счет за воду. Эту сумму вы должны либо вернуть, либо распечатать на консоли с округлением до двух знаков после запятой.

Вот два примера:

Input: 15
... Calculations which you do not need to output but here to help explain:
Tier I: 10*3.8476 = 38.476
Tier II: (15-10)*4.0932 = 20.466
Tier III: 0*4.9118 = 0
Tiers sum: 58.942
CPUC: 1.5% of 58.942 = 0.88413
LIRA: 0.047*15 = 0.705
PBOP: 0.004*15 = 0.06
Total sum: 58.942 + 0.88413 + 0.705 + 0.06 = 60.59113
...
Output: 60.59

Input: 100
... Calculations which you do not need to output but here to help explain:
Tier I: 10*3.8476 = 38.476
Tier II: 17*4.0932 = 69.5844
Tier III: (100-10-17)*4.9118 = 358.5614
Tiers sum: 466.6218
CPUC: 1.5% of  = 6.999327
LIRA: 0.047*100 = 4.7
PBOP: 0.004*100 = 0.4
Total sum: 478.721127
...
Output: 478.72

Это код гольф, поэтому выигрывает самый короткий код в байтах!


Пожалуйста, убедитесь, что мои изменения соответствуют вашим намерениям.
msh210

Да, спасибо @ msh210, это намного яснее, чем то, что у меня было
Даниэль

Если вы готовы потерять репутацию при голосовании с понижением, не могли бы вы объяснить, почему?
Даниэль

@Dopapp Некоторым людям может не понравиться этот вызов. Вы ничего не можете сделать там. Что бы это ни стоило, проблемы с понижением голоса не умаляют репутацию даунотера - только ответы.
Мего

Должны ли мы обрабатывать не целые числа n?
PurkkaKoodari

Ответы:


1

Pyth, 55 41 байт

.R+s*Vv.",9t¬®Ï0NwÝ"lMcUQ,T27*.051Q2

Код содержит непечатаемые символы, поэтому вот xxdhexdump.

00000000: 2e52 2b73 2a56 762e 222c 3904 1874 c2ac  .R+s*Vv.",9..t..
00000010: c2ae c280 c293 c38f 301c 4e77 c39d 226c  ........0.Nw.."l
00000020: 4d63 5551 2c54 3237 2a2e 3035 3151 32    McUQ,T27*.051Q2

объяснение

  1. ."…"это упакованная строка , которая содержит 3.8476,4.0932,4.9118.
  2. vоценивает это кортежу (3.8476, 4.0932, 4.9118). Это цены уровней, умноженные на добавленную цену CPUC.
  3. UQгенерирует диапазон 0... n-1.
  4. c,T27Разбивает этот диапазон на индексы 10 и 27, с дополнительными пустыми списками в конце, если диапазон слишком короткий.
  5. lM находит длину каждой части, давая количество воды для каждого уровня.
  6. *V умножает это на кортеж из шага 2, чтобы получить цены для уровней.
  7. s подводит итоги
  8. +*Q.051Добавляет вход, умноженный на 0,051, т.е. LIRA + PBOP.
  9. .R... 2округляет результат до 2 десятичных знаков.

Попробуйте онлайн.


2

Mathematica, 83 76 69 байт

1.015{3.8476,.2456(b=Boole)[#>10],.8186b[#>27],51/1015}&~Array~#~Total~2~Round~.01&

Анонимная функция, которая создает массив из трех уровней в первом столбце плюс LIRA и PBOP, представленные в виде числа с произвольной точностью в четвертом столбце. Все это умножается на, 1.015и все элементы массива суммируются и округляются до .01. Поскольку 51/1015*1.015будет желаемым, 0.051результат будет точно таким же, как указано в OP.

Более короткое решение, в 76 байтов , как я предложил в своем комментарии к решению Perl

{3.956314,.249284(b=Boole)[#>10],.830879b[#>27]}&~Array~#~Total~2~Round~.01&

где 1.015с самого начала учитываются цены, а затем добавляются LIRA и PBOP поверх первого уровня.

73 байта (но я не хочу обновлять мой счетчик байтов, поскольку это довольно близко к простому решению Perl):

69 байтов - ах, черт возьми, гольф тоже потребовал некоторых усилий.

.01Round[395.6314#+{24.9284,83.0879}.(UnitStep[#-1]#&/@{#-10,#-27})]&

РЕДАКТИРОВАТЬ относительно ошибки с плавающей запятой
Первые три итерации моего ответа действительно точны в их десятичном представлении, поскольку все задействованные коэффициенты имеют завершающие десятичные представления. Однако, поскольку коэффициенты являются явными числами с плавающей запятой, хранятся в двоичном формате и имеют не заканчивающиеся двоичные представления, достаточно большие входные данные начнут накапливать ошибки в младших разрядах двоичного представления. Я предполагаю, что когда число с плавающей запятой настолько велико, что оно соответствует только 3-4 цифрам справа от десятичной запятой, мы можем ожидать ошибки около 1 цента. Ниже приведен точный ответ.

72 байта, несколько невосприимчивых к неточностям поплавка

.01Round[{3956314,249284,830879}.(UnitStep[#-1]#&)/@(#-{0,10,27})/10^4]&

Умножение на ведущий .01делается на самом последнем шаге. До этого момента все вычисления выполняются с целыми числами. Это означает, что если .01опущен, будет точный результат, но выраженный в центах, а не в долларах. Конечно, умножение на число с плавающей точкой превращает все это в число с плавающей точкой, и, как уже упоминалось, оно должно быть достаточно маленьким, чтобы вмещаться в 64 бита, и при этом быть точным .01.


2

05AB1E, 64 58 51 байт

0T27¹)vy¹‚ï{0è})¥•_ÄÄ™wu24@•2'.:7ô)ø€PO¹"5.1"*+ïTn/

Разъяснения

0T27¹)                                               # list of price brackets
      vy¹‚ï{0è})                                     # min of each with input
                ¥                                    # calculate deltas to get amounts within each bracket
                 •_ÄÄ™wu24@•2'.:7ô                   # list of price rates with CPUC included
                                  )ø                 # zip with amounts for each rate
                                    €PO              # multiply amounts by their rates and sum
                                       ¹"5.1"*+      # add LIRA/PBOP
                                               ïTn/  # round to 2 decimals

Попробуйте онлайн


1

Perl 5, 73 байта

Очевидное решение. 72 байта, плюс 1 -neвместо -e.

printf'%.2f',$_*3.956314+($_-10)*($_>10)*.249284+($_-27)*($_>27)*.830879

Сохранено 5 байтов благодаря LLlAMnYP . Спасибо!


Что касается моего предыдущего комментария, то это редактирование фактически устраняет ошибки с плавающей запятой, которые вы имели в оригинале.
LLlAMnYP

@LLlAMnYP, конечно, любое приближение должно иметь ошибку для достаточно высокого значения ввода. Надеемся, что эта граница достаточно высока, чтобы ОП не заботился (потому что это неразумное количество воды для проживания одного человека).
msh210

@ msh210 Ты не знаешь историю Фреда !!
кот

Нет, потому что вы умножаете и добавляете числа с конечным десятичным представлением. Конечно, когда вы представляете их как float, они могут иметь не очень хорошее двоичное представление. Затем вы можете ожидать ошибки, когда представление с плавающей запятой допускает только 3-4 цифры справа от десятичной дроби. Мой «бонус-ответ» внизу моего поста преодолевает это, используя целые числа до самого последнего шага (который конвертирует центы в доллары). Если бы я пропустил умножение на .01, оно было бы точным, пока целое число может быть сохранено.
LLlAMnYP

1

Oracle SQL 11.2, 151 байт

SELECT ((DECODE(SIGN(:1-10),1,10,:1)*3.8476)+(DECODE(SIGN(:1-27),1,17,:1-10)*4.0932)+(DECODE(SIGN(:1-27),-1,0,:1-27)*4.9118))*1.015+:1*0.051 FROM DUAL;

Un-golfed

SELECT ((DECODE(SIGN(:1-10),1,10,:1)*3.8476)+
       (DECODE(SIGN(:1-27),1,17,:1-10)*4.0932)+
       (DECODE(SIGN(:1-27),-1,0,:1-27)*4.9118))*1.015+
       :1*0.051
FROM DUAL

Избавьтесь от пробела между ними SELECTи ((DECODEсохраните один байт. Сохраните больше 10 байтов, используя именованную таблицу! 7, удалив двоеточия и используя имя столбца с одним символом плюс три, используя имя таблицы с одним символом.
Джакомо Гарабелло

@Giacomo Garabello: удаление пробела всегда возвращает ноль с жабой и возвращает ошибку с SQLDeveloper. Скрипт создания таблицы добавляет более 10 байтов.
Джето

вам не нужно добавлять сценарий создания ... посмотрите здесь
Джакомо Гарабелло

1

JavaScript ES6, 77 байт

x=>(x>27?(x-27)*4.985477+109.681:(x>10?(x-10)*4.1546+39.053:x*3.9053))+.051*x

Un-golfed

f = x => {
  if (x > 27) {
    res = (x - 27) * 4.985477 + 109.681306
  } else if (x > 10) {
    res = (x - 10) * 4.154598 + 39.05314
  } else {
    res = x * 3.905314
  }
  return res + 0.051 * x
}

Я учел коэффициенты LIRA и PBOP. Дополнительные 1,5% добавляются в конце.

Вероятно, не самое эффективное решение с точки зрения игры в гольф, но несколько отличается от Perl.

Ошибка с плавающей запятой должна возникать с большими числами и может быть исправлена ​​добавлением 1 или 2 дополнительных байтов к каждому коэффициенту.

f=x=>(x>27?(x-27)*4.985477+109.681:(x>10?(x-10)*4.1546+39.053:x*3.9053))+.051*x

console.log(f(15))
console.log(f(100))
console.log(f(200000))


Вам не нужно ()s вокруг x>10?:, ?:партнеры справа налево. Я думаю, вы также можете сохранить несколько байтов, умножив скобки, например, (x-10)*4.154598+39.05314равно x*4.154598-41.54598+39.05314равно x*4.154598-2.49284.
Нил

1

R , 52 байта

approxfun(c(0,10,27,10^6),c(0,39.56,111.06,5036475))

Попробуйте онлайн!

Создает функцию линейного приближения, основанную на значениях моего предыдущего ответа 0,10,27 и 10 ^ 6. Подвох: верхний предел на входе 10 ^ 6.

approxfunecdf, stepfun, splinefunи т.д.) является одним из многих особенностей симпатичных из R.


0

VBA, 88 байт

Function W(V):W=Round(.051*V+.203*(V*19.238-(V-10)*(V>10)*1.228-(V-27)*(V>27)*4.093),2)
 

Базовая ставка и более высокие дифференциалы использования были умножены на 5, а множитель платы CPUC разделен на 5 (0,203).

Редактор VB добавит End Functionстроку, поэтому и включен перевод строки терминала.


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