가격 반올림으로 비용 절감


18

캐나다에서는 페니가 더 이상 유통되지 않습니다. 현금 결제는 가장 가까운 5 센트로 반올림됩니다.

구매를 분할하여 비용을 절약 할 수 있습니다. 예를 들어, $ 1.02 품목 2 개는 $ 2.04로 반올림하여 $ 2.05로 반올림하지만, 개별 구매로 품목을 구매할 때 각 가격은 $ 1.00로 반올림하여 총 $ 2.00입니다. 그러나 두 개의 품목을 각각 $ 1.03로 구매할 때는 한 번에 구매하는 것이 좋습니다.

돈을 절약하는 또 다른 방법은 반올림이 바람직하지 않은 경우 신용 카드를 사용하는 것입니다. 신용 결제는 반올림되지 않기 때문입니다. 2 개의 $ 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

루비, 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

빈 쇼핑 목록을 제공 할 때 알고리즘이 충돌하면 두 문자가 저장 될 수 있습니다.


추가로 2 문자 를 위해 s.reduce(:+)(일반적으로 당신은 paranthese가 필요하지 않지만 귀하의 경우에는 ...)로 변경하고 인라인으로 변경할 수 있습니다 m.
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 배열로 설정하여 한 문자를 저장할 수 있습니다.

온라인 테스트 사례

가장 흥미로운 속임수는 .2$>$비파괴 min연산자입니다.


수학에 대한 나의 분석은 본질적으로 Jan 및 Ray와 동일합니다. mod 5 값을 고려할 때 1 또는 2에 해당하는 거래 만 유일하게 절약됩니다. 신용 카드 옵션은 우리가 결코 반올림하지 않음을 의미합니다. 따라서 5n + 2 센트의 비용이 드는 아이템은 번들링을 통해 얻을 수 없습니다. 5n + 1 센트 가치가있는 품목도 없습니다 (1 센트 절약 2 개를 2 센트 절약으로 결합해도 아무런 이점이 없기 때문에). 유일한 흥미로운 예 3 및 4의 값을 포함 할 수 있도록 0, 첨가제 인 아이덴티티 3+3 = 13+4 = 4+4+4 = 2; 우리가 3과 4를 혼합했다면, 우리는 (엄청나게) 또는 (등가) 를 선호 3+4하여 최적화합니다 .3+34+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

매쓰 112 126 167 157

편집 : Peter Taylor와 cardboard_box 덕분에 {3, 3} 및 {4,4,4} 사례가 처리되었습니다.

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이됩니다. 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

파이썬 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)

파이썬 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 센트 항목을 결합하여 5 센트로 현금으로 지불하는 7 센트 구매와 반올림하므로 신용으로 지불하는 나머지 9 센트 항목을 얻을 수 있기 때문에 입력 값 [3,4,9]이을 제공해야 14합니다.
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

이 답변은 작업에 "total"이 포함되어 있지 않을 때 작성되었습니다.
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}

이 프로그램은 본질적으로 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
John Dvorak

활발한 개발중인 새로운 언어입니다. 그것은 다른 언어의 많은 힘을 결합합니다. 더 많은 사람들이 알 수 있기를 바랍니다.
Ray

당신이있는 경우 때문에 분석은 매우 완료되지 4 4 4 3 34 4 42 센트를 저장할 수있는 조합이지만, 그 방법이 최적이 아닌 그것을 구입. (실제로, 당신은 전혀 4 4 4고려 하지 않는 것 같습니다 .이 코드는 마지막 테스트 케이스에 실패하지 않습니까?)
Peter Taylor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.