通过四舍五入节省金钱


18

在加拿大,一分钱不再流通。现金付款四舍五入至最接近的5美分。

可以通过分割购买来节省金钱。例如,两个$ 1.02的商品的价格为$ 2.04,四舍五入为$ 2.05,但是在单独购买的商品中,每个价格四舍五入为$ 1.00,总计为$ 2.00。但是,当以1.03美元的价格购买两件商品时,最好一次购买。

另一种省钱的方法是,在四舍五入不利的情况下使用信用卡,因为未对信用卡付款进行四舍五入。如果我们要两个1.04美元的商品,则无论我们如何分割购买,总价格将合计为2.10美元。因此,我们应该使用信用卡支付这些物品。

编写一个函数或程序,该函数或程序接受以整数形式(以美分为单位)的商品价格列表,并输出可以通过一系列购买(可以现金或信用方式购买)实现的那些商品的最低总价(以美分)。

最短的代码胜出。

测试用例

[] : 0
[48] : 48
[92, 20] : 110
[47, 56, 45] : 145
[55, 6, 98, 69] : 225
[6, 39, 85, 84, 7] : 218
[95, 14, 28, 49, 41, 39] : 263
[92, 6, 28, 30, 39, 93, 53] : 335
[83, 33, 62, 12, 34, 29, 18, 12] : 273
[23, 46, 54, 69, 64, 73, 58, 92, 26] : 495
[19, 56, 84, 23, 20, 53, 96, 92, 91, 58] : 583
[3, 3, 19, 56, 3, 84, 3, 23, 20, 53, 96, 92, 91, 58, 3, 3] : 598
[2, 3, 4, 4, 4, 4, 4] : 19

Answers:


5

Ruby,119105个字符(93个正文)

def f s
a,b,c,d=(1..4).map{|i|s.count{|x|x%5==i}}
s.reduce(0,:+)-a-(c-m=c>d ?d:c)/2-2*(b+m+(d-m)/3)
end

如果算法允许在输入空的购物清单时崩溃,则可以保存两个字符。


您可以更改为s.reduce(:+)(通常甚至不需要括号,但在您的情况下...)并内联m额外的2个字符。
霍华德

当然了a,b,c,d=(1..4).map{|i|s.count{|x|x%5==i}}
霍华德

@Howard如果我0,reduce通话中删除,则代码将中断以输入为空。我在回答中确实提到了这一点。内联m似乎无济于事。感谢您的最后建议-这对我来说很愚蠢。
约翰·德沃夏克

1
你可以写给(c-m=c>d ?d:c)你两个字符。
霍华德

@Howard我认为这会中断,因为-优先级高于=。是赋值在其左侧具有高优先级(例如,确保左操作数是左值)?
约翰·德沃夏克

5

GolfScript(54个字符)

~]4,{){\5%=}+1$\,,}%~.2$>$:m- 3/m+@+2*@@m- 2/++~)+{+}*

这是一个将来自stdin的输入作为空格分隔的值的程序。可以通过强制输入格式改为GolfScript数组来保存一个字符。

在线测试用例

最有趣的技巧是.2$>$针对无损min运算符。


我对数学的分析与Jan和Ray的分析基本上相同:考虑值mod 5,唯一节省的是价值1或2的交易。信用卡选项意味着我们永远不会舍入。因此,价格为5n + 2美分的商品无法从捆绑中受益;价值5n + 1美分的商品也不会(因为将两个1美分的储蓄合并为2美分的储蓄没有任何好处)。0是添加剂身份,因此唯一感兴趣的情况下涉及的3和4的值3+3 = 13+4 = 4+4+4 = 2; 如果我们有混合3S和4S那么我们通过优化宁愿3+43+3(严格把好)或4+4+4(相当于)。


+1-尽管这些空格看起来很豪华;-) ~):m不幸的是,您可以通过保存-m()来删除它们,而不会减少字符数。
霍华德

@霍华德,我知道,我也尝试过。:D
Peter Taylor

3

C ++:126个字符

int P(int*m,int i){int t=0,h=0,d;while(i>-1){d=m[i]%5;t+=m[i--];d<3?t-=d:d==4?h++,t-=2:h--;}h<0?t+=h/2:t+=(h-h/3)*2;return t;}

欢迎给出指导以使该程序变得更短。这是测试程序,请使用tdm-gcc 4.7.1编译器编译并正常运行。

#include<iostream>
using namespace std;

//m[i]表示单个商品的价格,t表示所有商品总价格,
//d为单个商品价格取模后的值,h为单个商品价格取模后值为3的个数,
//f为单个商品价格取模后值为4的个数
int P(int*m,int i){int t=0,h=0,d;while(i>-1){d=m[i]%5;t+=m[i--];d<3?t-=d:d==4?h++,t-=2:h--;}h<0?t+=h/2:t+=(h-h/3)*2;return t;}

int main() {
int p1[1]={48};
int p2[2]={92,20};
int p3[3]={47,56,45};
int p4[4]={55,6,98,69};
int p5[5]={6,39,85,84,7};
int p6[6]={95,14,28,49,41,39};
int p7[7]={92,6,28,30,39,93,53};
int p8[8]={83,33,62,12,34,29,18,12};
int p9[9]={23,46,54,69,64,73,58,92,26};
int p10[10]={19,56,84,23,20,53,96,92,91,58};
int p11[10]={1,2,3,4,5,6,7,8,9,10};
cout<<P(p1,0)<<endl
    <<P(p2,1)<<endl
    <<P(p3,2)<<endl
    <<P(p4,3)<<endl
    <<P(p5,4)<<endl
    <<P(p6,5)<<endl
    <<P(p7,6)<<endl
    <<P(p8,7)<<endl
    <<P(p9,8)<<endl
    <<P(p10,9)<<endl
    <<P(p11,9)<<endl;

return 0;
}

1

R 143

function(x)min(sapply(rapply(partitions::listParts(length(x)),
                             function(i)min(sum(x[i]),5*round(sum(x[i])/5)),h="l"),
                      function(x)sum(unlist(x))))

测试(P上面的代码的别名在哪里)

> P(c(48))
[1] 48
> P(c(92, 20))
[1] 110
> P(c(47, 56, 45))
[1] 145
> P(c(55, 6, 98, 69))
[1] 225
> P(c(6, 39, 85, 84, 7))
[1] 218
> P(c(95, 14, 28, 49, 41, 39))
[1] 263
> P(c(92, 6, 28, 30, 39, 93, 53))
[1] 335
> P(c(83, 33, 62, 12, 34, 29, 18, 12))
[1] 273
> P(c(23, 46, 54, 69, 64, 73, 58, 92, 26))
[1] 495
> P(c(19, 56, 84, 23, 20, 53, 96, 92, 91, 58))
[1] 583

1

数学112 126 167 157

编辑:{3,3}和{4,4,4}的案例现在已经处理完毕,这要归功于Peter Taylor和纸板。

n_~g~o_ := {a___, Sequence @@ n, b___} :> {a, b, o};
f@s_ := Tr@Join[#[[2]], Sort@#[[1]] //. {1 -> 0, 2 -> 0, g[{3, 4}, 5], g[{3, 3}, 5], 
   g[{4, 4, 4}, 10]}] &[Transpose[{m = Mod[#, 5], # - m} & /@ s]]

注意:非购买(测试用例#1)输入为f[{0}]

怎么运行的

  1. 对于每种商品,无论付款方式如何,都将支付比相应价格少5的最大倍数。(没有解决这个问题。)
  2. Mod[n, 5]然后处理的其余部分:1和2变为0。零保持不变。
  3. 每对{3,4}-> {5}; 之后每对{3,3}-> {5};然后是三元组{4,4,4}-> {10}(如果适用)。
  4. 其余的4(如果有的话)保持不变(通过信用卡支付)。
  5. 5的原始倍数加上在步骤(2)至(4)中已调整(或未调整)的余数。

测试中

a12调整为{3,3} a13调整为{4,4,4}

a1={0};
a2={48};
a3={92,20};
a4={47,56,45};
a5={55,6,98,69} ;
a6={6,39,85,84,7};
a7={95,14,28,49,41,39};
a8={92,6,28,30,39,93,53};
a9={83,33,62,12,34,29,18,12};
a10={23,46,54,69,64,73,58,92,26};
a11={19,56,84,23,20,53,96,92,91,58};
a12={3,3,19,56,3,84,3,23,20,53,96,92,91,58,3,3};
a13={2,3,4,4,4,4,4};

f /@ {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13}

{0,48,110,145,225,218,263,335,273,495,583,598,19}


1
{3,3}呢?
彼得·泰勒

@PeterTaylor。好点子。它溜走了。
DavidC

{4,4,4}呢?我认为{3,4}-> {5},{3,3}-> {5}和{4,4,4}-> {10}(按顺序)应该给出最佳答案。
cardboard_box

@cardboard_box你是对的!查看更新。
DavidC

我在问题中添加了其他测试用例。我的那些是随机生成的,因此这些极端情况不会出现。
cardboard_box

1

Python 3(115个字符)

m=eval(input());t=a=b=0
for v in m:d=v%5;t+=v-d*(d<3);a+=d==3;b+=d==4
d=min(a,b);a-=d;b-=d;print(t-d*2-a//2-b//3*2)

Python 2(106个字符)

m=input();t=a=b=0
for v in m:d=v%5;t+=v-d*(d<3);a+=d==3;b+=d==4
d=min(a,b);a-=d;b-=d;print t-d*2-a/2-b/3*2

2
该问题要求总价,因此整个列表应该有一个输出。例如,输入值[3,4,9]应该为14,因为您可以将3美分和4美分的商品组合起来,以7美分的价格购买商品,您可以用5美分的现金支付,其余的9美分的商品则需要信用支付,因为否则会四舍五入。
cardboard_box

2
给定1, 2, 3, 4, 5, 6, 7, 8, 9, 10,这给出了0.0, 0.0, 2.5, 3.33, 5.0, 5.0, 5.0, 7.5, 8.33, 10.0,总和为46.66。但是,正确答案是45,因此您打印的数字总和不是正确答案,因此该解决方案是错误的。
Nolen皇族

当工作还不包含“总计”时写了这个答案
AMK

2
恐怕我不得不建议删除。阿斯克没有改变要求-他澄清了要求。如果分别需要每个商品的价格,那么为什么要提到“购买顺序/单次购买”并讨论哪个是有利的呢?
John Dvorak 2013年

我删除错误的答案。现在,这是最短的Python答案
AMK

0

APL,58个字符

{a b c d←+/(⍳4)∘.=5|⍵⋄(+/⍵)-a-(⌊2÷⍨c-m)-2×b+m+⌊3÷⍨d-m←c⌊d}

该程序实质上是Jan Dvorak的Ruby解决方案的直接翻译。


      {a b c d←+/(⍳4)∘.=5|⍵⋄(+/⍵)-a-(⌊2÷⍨c-m)-2×b+m+⌊3÷⍨d-m←c⌊d}⍬
0
      {a b c d←+/(⍳4)∘.=5|⍵⋄(+/⍵)-a-(⌊2÷⍨c-m)-2×b+m+⌊3÷⍨d-m←c⌊d}95 14 28 49 41 39
263
      {a b c d←+/(⍳4)∘.=5|⍵⋄(+/⍵)-a-(⌊2÷⍨c-m)-2×b+m+⌊3÷⍨d-m←c⌊d}19 56 84 23 20 53 96 92 91 58
583

是空向量。


0

朱莉娅83C

C=L->let
w,z,x,y=map(i->[i==x%5for x=L]|sum,1:4)
L|sum-(x+2w+3min(x,y)+4z)>>1
end

说明:

一次购买最多可节省2美分。因此,如果您有可以节省2美分的组合,请以这种方式购买,这样会很乐观。例如,如果您有x价格为3(mod 5)的y项目和价格为4(mod 5)的项目,则可以制作min(x, y)(3,4)对的数量,这样可以节省2 min(x, y)美分。然后,您使用剩余的3来节省您的max(0, x-min(x,y)) / 2美分。这也可以通过(max(x,y)-y)/2

w = sum(1 for p in prices if p % 5 == 1)
z = sum(1 for p in prices if p % 5 == 2)
x = sum(1 for p in prices if p % 5 == 3)
y = sum(1 for p in prices if p % 5 == 4)

ans = sum(prices) - (w + 2 z + 2 min(x, y) + div(max(x, y) - y, 2))
    = sum(prices) - (2w + 4z + 4 min(x, y) + x + y - min(x, y) - y) `div` 2
    = sum(prices) - (2w + 4z + 3 min(x, y) + x) `div` 2

编辑

该解决方案是错误的。


+1使用可能是有趣的学习一个相对陌生的语言
约翰·德沃夏克

这是一种正在积极开发中的新语言。它结合了来自不同语言的许多优势。希望更多的人能知道。
2013年

分析不是很完整,因为如果有的4 4 4 3 34 4 4,可以节省2美分的组合,但是以这种方式购买并不是最佳选择。(实际上,您似乎根本没有考虑4 4 4到这一点。这段代码不会使最后一个测试用例失败吗?)
Peter Taylor
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.