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


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.

approxfun(с ecdf, 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.