Dolar Bölünebilirliği ve Mükemmel Değişim


11

Cebimde 15 dolar var. Aynı şekilde, değişiklik yapmayan bir mağazadayım. Göz atarken, 10 ABD doları (vergi dahil) olan bir öğeyi tespit ederim. Para kaybetmeden bu ürünü alabilir miyim?

Bu durumda cevap evettir. Benim 15 $ nasıl bölünür olursa olsun (bir 10 ve bir 5 veya üç 5s, ya da başka bir şey), her zaman tam 10 $ gerekli olacaktır.

İkinci bir örnek olarak, cebimde 0.16 $ var. Tam olarak ne kadar para ödeyebilmeliyim?

Possible Divisions:
0.01, 0.05, 0.10
0.01, 0.05 x 3
0.01 x 16
Guaranteed Exact Change:
0.01, 0.05, 0.06, 0.10, 0.11, 0.15, 0.16

Cebimde 0.27 $ varsa ne olur?

Possible Divisions:
0.01 x 2, 0.25
0.01 x 2, 0.05, 0.10 x 2
0.01 x 2, 0.05 x 3, 0.10
0.01 x 2, 0.05 x 5
0.01 x 27
Guaranteed Exact Change:
0.01, 0.02, 0.25, 0.26, 0.27

Yukarıdaki durumda, her zaman mükemmel bir değişiklik yapacağım sadece birkaç miktar para vardı.

Senin görevin

A) tamsayı miktarda para ve B) olası mezheplerin bir listesini girdi olarak alır ve mükemmel bir değişiklik yapmam gereken para miktarlarının bir listesini çıkarır. Girdi STDIN veya program veya işlev için bağımsız değişkenler olabilir. Girdi biçimlendirmesinde çok katı olmayacağım; dil biçimlerinizin dizileriyle eşleşebilir.

Belki Daha Ayrıntılı Bir Açıklama

Cebimde bir dizi olası para gösterisinden oluşan belirli bir miktar param var. 8 dolarım varsa ve olası mezheplerin 2 $ ve 3 $ olduğunu biliyorsanız, o zaman cebimde olabilecek çok farklı fatura kombinasyonları var. Bunlar 2+2+2+2ve 3+3+2. Kesin miktarda para üretebilmek için, sadece cebimdeki faturaları kullanarak bu miktarı üretebilmeliyim. Dört tane 2 yaşım olsaydı, üretebilirdim 2, 4, 6, or 8. İki 3s ve 2 olsaydı, üretebilirim 2, 3, 5, 6, or 8Bu kombinasyonlardan hangisinin aslında cebimde olduğunu bilmediğim için son cevabım azaltıldı 2, 6, 8. Bunlar , toplam miktar ve olası mezhepler göz önüne alındığında, cebimden üretebileceğimi bildiğim değerler .

Elle Hesaplanan Örnek G / Ç

7 [3, 4]
3, 4, 7        //only one possible division into 3 + 4

7 [3, 2]
2, 3, 4, 5, 7  //the only division is 3 + 2 + 2

6 [2, 3, 4]
6     //divisions are 2+2+2, 3+3, 2+4 

16 [1, 5, 10, 25]          //this represents one of the examples above
1, 5, 6, 10, 11, 15, 16

27 [1, 5, 10, 25]          //another example from above
1, 2, 25, 26, 27

1500 [1, 5, 10, 25, 100, 500, 1000, 2000]
500, 1000, 1500

600 [100, 500, 1000, 2000]
100, 500, 600

600 [200, 1, 5, 10, 25, 100, 500, 1000, 2000]
600

Bu çok belirsiz.
motoku

@FryAmTheEggman "Belki daha ayrıntılı bir açıklama" ekledim. Hala kafa karıştırıcı olup olmadığını bana bildirin. (Ben de hemen hemen anlamsız olduğu için bir kenar davayı kaldırdım.)
PhiNotPi

Nasıl geldiğini anlamıyorum 6 [2, 3, 4]. Can 2+2+23 yapmak değil ve 3+32 ve 4 yapamaz?
xnor

@xnor haklısın, düzeltildi.
PhiNotPi

Program tüm girdiler için makul sürede mi çalışmalıdır? En kısa fikrim başlangıç ​​miktarında üstel ve 2 ^ 1500 çok şey var.
randomra

Yanıtlar:


2

Python 2, 200 197 193 140 bayt

f=lambda n,D,S={0}:sum([f(n-x,D,S|{x+y for y in S})for x in D],[])if n>0else[S]*-~n
g=lambda*a:(f(*a)and reduce(set.__and__,f(*a))or{0})-{0}

(İpuçları için @ Nabb'a teşekkürler)

İşe başlamak için şu an için kötü bir golf çözümü. İle çağrı g(16, [1, 5, 10, 25])- çıktı, ilgili mezhepleri olan bir kümedir.

Yaklaşım basittir ve iki adıma ayrılmıştır:

  • fnmezheplerle ulaşmanın tüm yollarına bakar D(örneğin [1, 5, 10]) ve her biri için bu mezheplerle (örneğin set([0, 1, 5, 6, 10, 11, 15, 16])) yapılabilecek tüm miktarları bulur .
  • gsonuçlarının kesişimlerini hesaplar f, daha sonra son cevap için 0'ı kaldırır.

Program, 1-5 ve 7 numaralı vakaları çözer, yığın 6'da taşar ve sonsuza kadar 8 alır.

Çözüm yoksa (örn. g(7, [2, 4, 6])), Program boş bir küme döndürür. Böyle bir durum için bir hata verilmesine izin verilirse, işte daha kısa g:

g=lambda*a:reduce(set.__and__,f(*a))-{0}

g=lambda L,c=0:L and g(L[1:],c)|g(L,c+L.pop(0))or{c}biraz daha kısa
Nabb

-{0}[L]*-~n[L][-n:]
B'ye gelerek

1

JavaScript (ES6) 162 203 207

Düzenle r dizisindeki sonuç kümelerini kesmenin yolunu değiştirdi. Biraz daha hızlı, ama algoritma hala kokuyor.

Daha ayrıntılı bir açıklama gelecektir.
Kısaca: c, olası tüm alt bölümleri numaralandıran özyinelemeli bir işlevdir. k yinelemesiz tüm olası toplamları numaralandıran özyinelemeli bir işlevdir. K işleviyle bulunan herhangi bir yeni sonuç kümesi önceki bulunanla karşılaştırılır, yalnızca ortak sonuçlar korunur.

Neden bu kadar yavaş? Hedef toplamı, örneğin 1500'ü ve tek bir değer 1'i yönetmek zorunda olmak, tüm olası toplamları numaralandırmak iyi bir fikir değildir.

F=(s,d,r,
  c=(s,i,t=[],v,k=(i,s,v)=>{for(;v=t[i++];)k(i,s+v);o[s]=s})=>
  {for(s||(i=k(o=[],0),r=(r||o).filter(v=>o[v]));v=d[i];++i)s<v||c(s-v,i,[...t,v])}
)=>c(s,0)||r

Ungolfed

F=(s,d)=>{
  var r
  var c=(s,i,t=[])=>
  {
    var o=[],v
    var k=(i,s)=> // find all sums for the current list t, set a flag in the o array
    {
      var v
      for(;v=t[i++];)k(i,s+v)
      o[s]=s
    }

    if (s==0) {
      k(0,0)
      if (r)
        r = r.filter(v=>o[v]) // after first loop, intersect with current
      else
        r = o.filter(v=>v) // first loop, keep all results
    } 
    else
      for(;v=d[i];++i)
      { 
        if (s >= v) 
          c(s-v, i, t.concat(v))
      }
  }
  c(s,0) // enumerate all possible set of pieces
  return r
}

Firefox / FireBug konsolunda test et

F(16,[1,5,10,25])

[1, 5, 6, 10, 11, 15, 16]

(süre 84 milisaniye)

F(27, [1, 5, 10, 25]) 

[1, 2, 25, 26, 27]

(zaman 147252 milisaniye, çok hızlı değil)


0

Wolfram Methematica, 104 bayt

Rest@*Intersection@@Map[Total]/@Subsets/@Union[Sort/@IntegerPartitions[#,#,PadLeft[{},Length[#2]#,#2]]]&

Ungolfed (sondan okuyun):

Rest@* // Removing 0
  Intersection@@   // Intersecting all totals
     Map[Total]/@  // Counting total of each subset
        Subsets/@  // Getting all the subsets of each partition
           Union[  // Removing duplicates 
              Sort/@ // Sorting each partition (to remove duplicates next)
                 IntegerPartitions[#,#,PadLeft[{},Length[#2]#,#2]] // Getting all Integer partitions
                ]&
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.