Fiyat yuvarlama ile tasarruf edin


18

Kanada'da, kuruş artık dolaşmıyor. Nakit ödemeler en yakın 5 sente yuvarlanır.

Para, satın alımları bölerek tasarruf edilebilir. Örneğin, iki 1,02 dolarlık öğe 2,05 dolara mal olur, ancak öğeleri ayrı satın alımlarda satın alırken, her bir fiyat toplam 2,00 dolar için 1,00 dolara yuvarlanır. Bununla birlikte, her biri 1.03 $ 'dan iki ürün satın alırken, bunları tek bir satın alımda satın almak daha iyidir.

Para biriktirmenin bir başka yolu, kredi ödemeleri yuvarlanmadığından, yuvarlama uygun olmadığında kredi kartı kullanmaktır. İki $ 1.04 ürün istiyorsak, satın alma işlemlerini nasıl böldüğümüzden bağımsız olarak toplam fiyat 2.10 $ 'a kadar yuvarlanır. Bu nedenle, bu ürünler için kredi kartıyla ödeme yapmalıyız.

Maddelerin fiyat listesini sent olarak tamsayı olarak kabul eden ve her biri nakit veya kredi ile bir dizi satın alma yoluyla elde edilebilen ürünler için mümkün olan en düşük toplam fiyatı (sent olarak) veren bir işlev veya program yazın.

En kısa kod kazanır.

Test senaryoları

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

Yanıtlar:


5

Ruby, 119105 karakter (93 gövde)

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

Boş bir alışveriş listesine beslendiğinde algoritmanın çökmesine izin verilirse iki karakter kaydedilebilir.


Ek olarak 2 karakter için s.reduce(:+)(normalde parantezlere ihtiyacınız yok, ancak sizin durumunuzda ...) ve satır içi molarak değiştirebilirsiniz.
Howard

Ve tabii ki a,b,c,d=(1..4).map{|i|s.count{|x|x%5==i}}.
Howard

@Howard ben kaldırırsanız 0,gelen reduceboş girişi için, çağrı kodu sonları. Cevapta bahsetmiştim. Inlining m yardımcı görünmüyor. Son öneri için teşekkürler - bu benden aptalcaydı.
John Dvorak

1
Size (c-m=c>d ?d:c)iki karakter veren yazabilirsiniz .
Howard

@Bunun kırılacağını düşündüm çünkü -önceliğe göre daha yüksek önceliğe sahip =. Görevin sol tarafında yüksek önceliği var mı (sol işlenenin bir değer olması için olduğu gibi)?
John Dvorak

5

GolfScript (54 karakter)

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

Bu stdin'den boşlukla ayrılmış değerler olarak girdi alan bir programdır. Bir karakter, giriş formatı yerine GolfScript dizileri olarak zorlanarak kaydedilebilir.

Online test senaryoları

En ilginç numara, .2$>$yıkıcı olmayan bir minoperatör içindir.


Matematik analizim aslında Jan's ve Ray's ile aynıdır: mod 5 değerleri göz önüne alındığında, tek tasarruf 1 veya 2 değerindeki işlemlerde olur. Kredi kartı seçeneği asla yuvarlanmayacağımız anlamına gelir. Yani 5n + 2 sente mal olan bir ürün paketlemeden faydalanamaz; 5n + 1 sent değerinde bir ürün de olamaz (çünkü iki 1 kuruşluk tasarrufu 2 kuruşluk bir tasarrufla birleştirmenin faydası yoktur). 0 ilave kimliktir, bu nedenle tek ilginç durum 3 ve 4 değerlerini içerir. 3+3 = 1Ve 3+4 = 4+4+4 = 2; 3'leri ve 4'leri karıştırırsak 3+4, 3+3(kesinlikle daha iyi) veya 4+4+4(eşdeğer) tercih ederek optimize ederiz .


+1 - bu boşluklar çok gösterişli görünse de ;-) ~):mMaalesef karakter sayısında bir azalma olmadan -m ( ) 'yi kaydederek bunları kaldırabilirsiniz .
Howard

@Howard, biliyorum, ben de denedim. : D
Peter Taylor

3

C ++: 126 karakter

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

Test programı, tdm-gcc 4.7.1 derleyici ile derlemek ve normal şekilde çalıştırmak için rehberlik vermek hoş geldiniz.

#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

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

Testler ( Pyukarıdaki kod için bir takma ad nerede )

> 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

Düzenleme : Peter Taylor ve karton kutu sayesinde artık {3, 3} ve {4,4,4} vakaları ele alındı.

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

Not: Satın almama (test durumu # 1) olarak girilir f[{0}].

Nasıl çalışır

  1. Her bir kalem için, ödeme şekline bakılmaksızın, ilgili fiyattan en az 5'inin en büyük katı ödenecektir. (Bunu atlatmak yok.)
  2. Daha Mod[n, 5]sonra geri kalanlar işlenir: 1'ler ve 2'ler 0 olur. Sıfırlar değişmeden kalır.
  3. Her bir çift {3, 4} -> {5}; daha sonra her bir çift {3, 3} -> {5}; ardından üçlü {4,4,4} -> {10}, varsa.
  4. Kalan 4'ler (varsa) değişmeden kalır (kredi kartı ile ödenir).
  5. 5'in orijinal katları, (2) ila (4) adımlarında ince ayarlanmış (veya değiştirilmemiş) kalıntılarla toplanmıştır.

Test yapmak

a12{3,3} için a13ayarlar {4,4,4} için ayarlar

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} ne olacak?
Peter Taylor

@PeterTaylor. İyi bir nokta. Tarafından kaymış.
DavidC

{4,4,4} hakkında ne düşünüyorsunuz? Sanırım {3,4} -> {5}, {3,3} -> {5} ve {4,4,4} -> {10} (bu sırayla) ile en uygun cevapları vermelidir.
cardboard_box

@cardboard_box Haklısın! Güncellemeye bakın.
DavidC

Soruya ek test durumlarınızı ekledim. Sahip olduğumlar rastgele üretildi, bu yüzden bu köşe vakaları görünmedi.
cardboard_box

1

Python 3 (115 karakter)

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

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
Soru toplam fiyatı ister, bu nedenle tüm liste için bir çıktı olmalıdır. Örneğin, girdinin [3,4,9]vermesi gerekir 14, çünkü 3 sent ile 4 sent ile nakit olarak ödediğiniz 7 sentlik bir satın alma ve aksi takdirde yuvarlanması nedeniyle kredi ile ödediğiniz kalan 9 cent'lik ürünü almak için birleştirebilirsiniz.
karton_box

2
Verilen 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, bu verir 0.0, 0.0, 2.5, 3.33, 5.0, 5.0, 5.0, 7.5, 8.33, 10.0, toplamı 46.66. Ancak, doğru cevap 45, bu nedenle yazdırdığınız sayıların toplamı doğru cevap değildir ve bu nedenle bu çözüm yanlıştır.
Nolen Royalty

Bu cevap, iş henüz "toplam" içermediğinde işlendi
AMK

2
Korkarım silme önermek zorundayım. Asker gereksinimleri değiştirmedi - onları açıkladı. Her bir kalem için ayrı ayrı fiyat isteniyorsa, neden bir "satın alma sırası / tek satın alma" ve hangisinin uygun olduğu tartışmasından bahsediliyor?
John Dvorak

Yanlış cevapları siliyorum. Şimdi en kısa Python cevapları
AMK

0

APL, 58 karakter

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

Program aslında Jan Dvorak'ın Ruby çözümünün doğrudan çevirisidir .


      {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

boş vektördür.


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

Açıklama:

Bir satın alma işleminde en fazla 2 sent tasarruf edebilirsiniz. Yani size 2 kuruş kurtarabilecek bir kombinasyonunuz varsa, sadece bu şekilde satın alın ve iyimser olacaktır . Örneğin, xfiyatı 3 (mod 5) olan ve yfiyat 4 (mod 5) olan öğeleriniz varsa, sizi min(x, y)kurtaracak sayıda (3, 4) çift yapabilirsiniz 2 min(x, y). Sonra size geri kalanı 3, varsa, max(0, x-min(x,y)) / 2kuruş kurtarmak için kullanın . Bu ayrıca şu şekilde hesaplanabilir:(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

Düzenle

Bu çözüm yanlış.


Öğrenmesi ilginç olabilecek nispeten bilinmeyen bir dili kullanmak için +1
John Dvorak

Aktif gelişme altında yeni bir dil. Farklı dillerden birçok güç birleştirir. Daha fazla insanın bunu bilmesini umuyoruz.
Ray

Eğer varsa, çünkü analizi, tam anlamıyla bitmedi 4 4 4 3 3daha sonra 4 4 42 sent kaydedebilen bir kombinasyonudur, ama bu şekilde optimal değildir bunu satın. (Aslında, hiç 4 4 4dikkate almıyorsunuz. Bu kod son test durumunda başarısız değil mi?)
Peter Taylor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.