ประหยัดเงินด้วยการปัดเศษราคา


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

คำตอบ:


5

Ruby, 119 105 ตัว (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 ตัวอักษรเพิ่มเติม
Howard

a,b,c,d=(1..4).map{|i|s.count{|x|x%5==i}}และแน่นอน
Howard

@Howard ถ้าฉันลบออก0,จากการreduceโทรรหัสจะแบ่งสำหรับการป้อนข้อมูลที่ว่างเปล่า ฉันพูดถึงมันในคำตอบ การฝัง m ดูเหมือนจะไม่ช่วย ขอบคุณสำหรับคำแนะนำสุดท้าย - นั่นช่างโง่จากฉัน
John Dvorak

1
คุณสามารถเขียน(c-m=c>d ?d:c)ที่ให้สองตัวอักษร
Howard

@Howard ผมคิดว่าจะแตกเพราะมีความสำคัญสูงกว่า- =มันเป็นสิ่งที่ได้รับมอบหมายมีความสำคัญสูงทางด้านซ้ายของมัน (เช่นในเพื่อให้แน่ใจว่าตัวถูกดำเนินการด้านซ้ายเป็น lvalue)?
John Dvorak

5

GolfScript (54 ตัวอักษร)

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

นี่คือโปรแกรมที่รับอินพุตจาก stdin เป็นค่าคั่นด้วยช่องว่าง สามารถบันทึกอักขระหนึ่งตัวได้โดยบังคับให้รูปแบบอินพุตแทนเป็น GolfScript Array

กรณีทดสอบออนไลน์

เคล็ดลับที่น่าสนใจที่สุด.2$>$สำหรับminผู้ประกอบการที่ไม่ทำลาย


การวิเคราะห์ทางคณิตศาสตร์ของฉันเป็นหลักเหมือนกับ Jan's และ Ray's: เมื่อพิจารณาถึงค่า mod 5 การประหยัดเพียงอย่างเดียวคือธุรกรรมที่มีมูลค่า 1 หรือ 2 ตัวเลือกบัตรเครดิตหมายความว่าเราไม่เคยปัดเศษ ดังนั้นรายการที่มีราคา 5n + 2 เซ็นต์จึงไม่ได้ประโยชน์จากการรวมกลุ่ม และไม่สามารถรายการมีค่า 5n + 1 เซ็นต์ (เพราะการรวมการออม 1 เซนต์สองครั้งเข้ากับการประหยัด 2 เซ็นต์จะไม่ให้ประโยชน์ใด ๆ ) 0 เป็นเอกลักษณ์การบวกดังนั้นกรณีที่น่าสนใจมีส่วนเกี่ยวข้องกับค่านิยมของ 3 และ 4 3+3 = 1และ3+4 = 4+4+4 = 2; ถ้าเรามี 3s ผสมและ 4s แล้วเราเพิ่มประสิทธิภาพโดยเลือกที่3+4มากกว่า3+3(อย่างเคร่งครัดดีกว่า) หรือ4+4+4(เทียบเท่า)


+1 - แม้ว่าช่องว่างเหล่านั้นจะดูฟุ่มเฟือยมาก ;-) คุณสามารถลบออกได้โดยการบันทึก -m ( ~):m) น่าเสียดายที่ไม่มีการลดจำนวนถ่าน
Howard

@Howard ฉันรู้ฉันก็ลองเหมือนกัน : 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

Mathematica 112 126 167 157

แก้ไข : กรณีของ {3, 3} และ {4,4,4} ตอนนี้จัดการได้โดย Peter Taylor และ cardboard_box

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} ล่ะ
Peter Taylor

@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 Royalty

คำตอบนี้เขียนเมื่องานที่ยังไม่มีคำว่า "รวม"
AMK

2
ฉันเกรงว่าฉันจะต้องแนะนำการลบ Asker ไม่ได้เปลี่ยนแปลงข้อกำหนด - เขาชี้แจงพวกเขา หากต้องการราคาสำหรับแต่ละรายการแยกกันทำไมถึงพูดถึง "ลำดับของการซื้อ / การซื้อครั้งเดียว" และการอภิปรายว่ารายการใดเป็นที่นิยม
John Dvorak

ฉันลบคำตอบที่ผิด ตอนนี้เป็นคำตอบที่สั้นที่สุดของ Python
AMK

0

APL, 58 ตัวอักษร

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

โปรแกรมเป็นหลักแปลตรงของการแก้ปัญหาทับทิม ม.ค. Dvorak ของ


      {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 สำหรับการใช้ภาษาที่ค่อนข้างไม่รู้จักซึ่งอาจน่าสนใจในการเรียนรู้
John Dvorak

เป็นภาษาใหม่ภายใต้การพัฒนาที่ใช้งานอยู่ มันรวมความหลากหลายมากมายจากภาษาที่แตกต่างกัน หวังว่าคนอื่นจะรู้ได้
เรย์

การวิเคราะห์ไม่ได้ค่อนข้างสมบูรณ์เพราะถ้าคุณมี4 4 4 3 3แล้ว4 4 4คือการรวมกันซึ่งสามารถบันทึก 2 เซนต์ แต่ซื้อมันด้วยวิธีที่ไม่ดีที่สุด (อันที่จริงแล้วคุณไม่ได้คำนึง4 4 4ถึงเลยรหัสนี้ไม่ได้ล้มเหลวในการทดสอบครั้งสุดท้ายใช่ไหม)
Peter Taylor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.