Tiết kiệm tiền với làm tròn giá


18

Ở Canada, đồng xu không còn được lưu hành. Thanh toán tiền mặt được làm tròn đến 5 xu gần nhất.

Tiền có thể được tiết kiệm bằng cách chia nhỏ mua hàng. Ví dụ: hai mặt hàng $ 1,02 có giá 2,04 đô la làm tròn lên tới 2,05 đô la, nhưng khi mua các mặt hàng trong các giao dịch mua riêng lẻ, mỗi mức giá làm tròn thành 1 đô la với tổng số tiền là 2 đô la. Tuy nhiên, khi mua hai mặt hàng với giá 1,03 đô la mỗi mặt hàng, tốt hơn là mua chúng trong một lần mua.

Một cách khác để tiết kiệm tiền là sử dụng thẻ tín dụng khi làm tròn không thuận lợi, vì thanh toán tín dụng không được làm tròn. Nếu chúng tôi muốn hai mặt hàng 1,04 đô la, tổng giá sẽ làm tròn lên tới 2,10 đô la bất kể chúng tôi chia các giao dịch mua như thế nào. Do đó, chúng ta nên thanh toán cho các mặt hàng này bằng thẻ tín dụng.

Viết hàm hoặc chương trình chấp nhận danh sách giá của các mặt hàng dưới dạng số nguyên tính bằng xu và đưa ra tổng giá thấp nhất có thể (tính bằng xu) cho các mặt hàng có thể đạt được thông qua chuỗi mua hàng, từng khoản bằng tiền mặt hoặc bằng tín dụng.

Mã ngắn nhất sẽ thắng.

Các trường hợp thử nghiệm

[] : 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

Câu trả lời:


5

Ruby, 119 105 ký tự (93 cơ thể)

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

Hai ký tự có thể được lưu nếu thuật toán được phép gặp sự cố khi được cung cấp danh sách mua sắm trống.


Bạn có thể thay đổi thành s.reduce(:+)(thông thường bạn thậm chí không cần parantantes, nhưng trong trường hợp của bạn ...) và nội tuyến mcho thêm 2 ký tự.
Howard

Và tất nhiên a,b,c,d=(1..4).map{|i|s.count{|x|x%5==i}}.
Howard

@Howard nếu tôi xóa 0,khỏi reducecuộc gọi, mã sẽ bị hỏng cho đầu vào trống. Tôi đã đề cập đến điều đó trong câu trả lời. Nội tuyến m dường như không giúp được gì. Cảm ơn lời đề nghị cuối cùng - đó là ngu ngốc từ tôi.
John Dvorak

1
Bạn có thể viết (c-m=c>d ?d:c)mà cung cấp cho bạn hai ký tự.
Howard

@Howard Tôi nghĩ rằng sẽ phá vỡ vì -có mức độ ưu tiên cao hơn =. Có phải là nhiệm vụ có mức độ ưu tiên cao ở phía bên trái của nó (như trong, để đảm bảo toán hạng bên trái là một giá trị)?
John Dvorak

5

GolfScript (54 ký tự)

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

Đây là một chương trình lấy đầu vào từ stdin làm giá trị phân tách bằng dấu cách. Một ký tự có thể được lưu bằng cách buộc định dạng đầu vào thay vào đó là mảng GolfScript.

Các trường hợp thử nghiệm trực tuyến

Thủ thuật thú vị nhất là .2$>$cho một mintoán tử không phá hủy .


Phân tích toán học của tôi về cơ bản giống như của Jan và Ray: xem xét các giá trị mod 5, tiết kiệm duy nhất là cho các giao dịch có giá trị 1 hoặc 2. Tùy chọn thẻ tín dụng có nghĩa là chúng tôi không bao giờ làm tròn số. Vì vậy, một mặt hàng có giá 5n + 2 xu không thể hưởng lợi từ việc đóng gói; một mặt hàng trị giá 5n + 1 xu cũng không thể (vì kết hợp hai khoản tiết kiệm 1 xu vào khoản tiết kiệm 2 xu không mang lại lợi ích gì). 0 là danh tính phụ gia, vì vậy các trường hợp thú vị duy nhất liên quan đến các giá trị của 3 và 4. 3+3 = 13+4 = 4+4+4 = 2; nếu chúng ta đã trộn 3 giây và 4 thì chúng ta tối ưu hóa bằng cách thích 3+4hơn 3+3(hoàn toàn tốt hơn) hoặc 4+4+4(tương đương).


+1 - mặc dù các không gian đó trông rất xa hoa ;-) Bạn có thể xóa chúng bằng cách lưu -m ( ~):m) không may mà không giảm số lượng char.
Howard

@Howard, tôi biết, tôi cũng đã thử nó. : D
Peter Taylor

3

C ++: 126 ký tự

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;}

Chào mừng bạn đến với hướng dẫn để đưa chương trình này trở nên ngắn hơn. Đây là chương trình thử nghiệm, biên dịch với trình biên dịch tdm-gcc 4.7.1 và chạy bình thường.

#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))))

Các thử nghiệm (trong đó Pcó một bí danh cho mã ở trên)

> 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

Toán học 112 126 167 157

Chỉnh sửa : Các trường hợp {3, 3} và {4,4,4} hiện đã được xử lý nhờ Peter Taylor và các tông_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]]

Lưu ý: Không mua hàng (trường hợp thử nghiệm số 1) được nhập dưới dạng f[{0}].

Làm thế nào nó hoạt động

  1. Đối với mỗi mặt hàng, bội số lớn nhất của 5 ít hơn giá tương ứng sẽ được thanh toán bất kể hình thức thanh toán. (Không có xung quanh đó.)
  2. Phần còn lại Mod[n, 5]sau đó được xử lý: 1 và 2 trở thành 0. Số không thay đổi.
  3. Mỗi cặp {3, 4} -> {5}; sau đó mỗi cặp {3, 3} -> {5}; sau đó gấp ba, {4,4,4} -> {10}, nếu có.
  4. 4 giây còn lại, nếu có, vẫn không thay đổi (thanh toán bằng thẻ tín dụng).
  5. Bội số gốc của 5 tổng cộng với phần dư được điều chỉnh (hoặc không) trong các bước (2) đến (4).

Kiểm tra

a12điều chỉnh cho {3,3} a13điều chỉnh cho {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
Còn {3,3} thì sao?
Peter Taylor

@PeterTaylor. Điểm tốt. Nó trượt qua.
DavidC

Còn {4,4,4} thì sao? Tôi nghĩ với {3,4} -> {5}, {3,3} -> {5} và {4,4,4} -> {10} (theo thứ tự đó) sẽ cho câu trả lời tối ưu.
tông_box

@cardboard_box Bạn nói đúng! Xem cập nhật.
DavidC

Tôi đã thêm các trường hợp kiểm tra bổ sung của bạn vào câu hỏi. Những cái tôi đã được tạo ngẫu nhiên để những trường hợp góc đó không xuất hiện.
tông_box

1

Python 3 (115 ký tự)

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 ký tự)

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
Câu hỏi yêu cầu tổng giá, vì vậy cần có một đầu ra cho toàn bộ danh sách. Ví dụ: đầu vào [3,4,9]sẽ cung cấp 14, bởi vì bạn có thể kết hợp các mặt hàng 3 và 4 xu để mua 7 xu mà bạn trả bằng tiền mặt với 5 xu và 9 xu còn lại bạn thanh toán bằng tín dụng vì nếu không sẽ làm tròn số.
tông_box

2
Cho 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, cái này cho 0.0, 0.0, 2.5, 3.33, 5.0, 5.0, 5.0, 7.5, 8.33, 10.0, mà tổng 46.66. Tuy nhiên, câu trả lời đúng là 45, do đó tổng các số bạn in không phải là câu trả lời đúng và do đó giải pháp này không chính xác.
Nolen Royalty

Câu trả lời này đã được viết khi công việc chưa chứa "tổng"
AMK

2
Tôi sợ tôi phải đề nghị xóa. Asker đã không thay đổi các yêu cầu - ông đã làm rõ chúng. Nếu giá cho từng mặt hàng riêng biệt được mong muốn, thì tại sao lại đề cập đến "chuỗi mua hàng / mua một lần" và thảo luận về mặt hàng nào là thuận lợi?
John Dvorak

Tôi xóa câu trả lời sai. Bây giờ là câu trả lời ngắn nhất về Python
AMK

0

APL, 58 ký tự

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

Chương trình này thực chất là bản dịch trực tiếp giải pháp Ruby của Jan 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

là vector trống.


0

Julia 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

Giải thích:

Trong một lần mua, bạn có thể tiết kiệm tối đa 2 xu. Vì vậy, nếu bạn có một sự kết hợp có thể giúp bạn tiết kiệm 2 xu, chỉ cần mua theo cách đó và nó sẽ rất lạc quan . Ví dụ: nếu bạn có xcác mặt hàng có giá 3 (mod 5) và ycác mặt hàng có giá 4 (mod 5), bạn có thể tạo min(x, y)số lượng cặp (3, 4), giúp bạn tiết kiệm 2 min(x, y)xu. Sau đó, bạn sử dụng 3 phần còn lại, nếu có, để tiết kiệm cho bạn max(0, x-min(x,y)) / 2xu. Điều này cũng có thể được tính bằng(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

Biên tập

Giải pháp này là sai.


+1 để sử dụng một ngôn ngữ tương đối lạ có thể thú vị để học
John Dvorak

Đó là một ngôn ngữ mới đang được phát triển tích cực. Nó kết hợp nhiều st Hardh từ các ngôn ngữ khác nhau. Hy vọng rằng nhiều người có thể biết nó.
Ray

Phân tích chưa hoàn chỉnh, bởi vì nếu bạn có 4 4 4 3 3thì đó 4 4 4là một sự kết hợp có thể tiết kiệm 2 xu, nhưng mua nó theo cách đó không tối ưu. (Trên thực tế, dường như bạn hoàn toàn không tính 4 4 4đến. Mã này có thất bại trong trường hợp thử nghiệm cuối cùng không?)
Peter Taylor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.