弗雷德的水费单


9

弗雷德(Fred)是一个准友善的人,但实际上他是卑鄙的。

因此,弗雷德一个人住在加利福尼亚洛斯阿尔托斯的一间小公寓里。弗雷德之所以如此刻薄,是因为他对水非常专一。因此,他需要您的帮助来弄清自己的水费单。

您的工作是编写一个函数或程序,该函数或程序在给定用作输入水的量(始终为整数)的情况下返回其水费账单。

耗水量是分层的。这意味着价格取决于水的数量。

这些是其对应的等级,价格和水量:

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

第一层,第二层,第三层,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 '16

是的,感谢@ msh210,这比我的要清楚得多
Daniel

如果您愿意在否决权上浪费声誉,至少可以解释一下原因吗?
丹尼尔(Daniel)

@Dopapp有些人可能不喜欢挑战。您无能为力。就其价值而言,拒绝投票的挑战并不能从拒绝投票者的声誉中减去-只是答案。
Mego

我们必须处理非整数n吗?
PurkkaKoodari

Answers:


1

Pyth,55 41字节

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

该代码包含不可打印的字符,因此这是一个xxd十六进制转储。

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生成范围0n-1
  4. c,T27在索引10和27处拆分该范围,如果范围太短,则在末尾添加多余的空列表。
  5. lM 找到每个部分的长度,给出每一层的水量。
  6. *V 将其乘以第2步中的元组,得到各层的价格。
  7. s 对结果求和。
  8. +*Q.051将输入乘以0.051,即LIRA + PBOP。
  9. .R2将结果四舍五入到两位小数。

在线尝试。


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中的规格完全一样精确。

正如我在Perl解决方案下的评论中所建议的那样,一个较短的解决方案(76字节)

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

其中1.015被计入价格从一开始,然后里拉和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

由于LLlAMnYP节省了5个字节。谢谢!


在我之前的评论中,此编辑实际上消除了原始版本中的浮点错误。
LLlAMnYP'6

@LLlAMnYP,对于任何足够高的输入值,肯定任何近似都必须具有误差。希望这个界限足够高,以至于OP不在乎(因为对于一个人的住所来说这是不合理的水量)。
msh210 '16

@ msh210你不知道弗雷德的故事!

不可以,因为您要使用有限的十进制表示形式对数字进行乘法和加法运算。当然,当您将它们表示为浮点数时,它们的二进制表示可能不太好。然后,当浮点表示形式仅允许小数点右边的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;

未打高尔夫球

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通过删除冒号并使用一个char列名称加上三个使用一个char表名称的方式。
Giacomo Garabello

@Giacomo Garabello:删除空格总是使用toad返回null,并且使用SQLDeveloper返回错误。创建表脚本添加了超过10个字节。
Jeto 2016年

您不必添加创建脚本... 看这里
Giacomo Garabello,2016年

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

未打高尔夫球

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.05314equals x*4.154598-41.54598+39.05314equals 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(有ecdfstepfunsplinefun,等)的许多不错的功能之一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一行,这就是为什么包含终端换行的原因。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.