Fuar kralı için sekiz madeni para


22

Bu, başka bir bulmacanın, bir "muadili" dir adil kral için Sekiz sikke Puzzling.SE üzerinde.

Yukarıdaki bulmacayı arka plan için okuyabilirsiniz. Bu yapbozun detayları aşağıdaki gibidir.

Farklı değerlerde 8 çeşit madeni para seti oluşturulur, kral, maksimum N'yi bulmanızı ister, böylece 0'dan N'ye kadar olan herhangi bir fiyat, en fazla 8 madeni paradan oluşan bir kombinasyonla ve masrafsız olarak ödenebilir.

Örneğin, (Glorfindel'in cevabından alınmıştır). 1, 2, 5, 13, 34, 89, 233, 610 değerlerine sahip bir madeni para seti verilirse, programınız 1596 vermelidir, çünkü 0 ile 1596 arasındaki her sayı (dahil) artıkların toplamı ile gösterilemez. verilen listedeki 8 sayıdan (sayı tekrarlanabilir), 1597 bu şekilde temsil edilemez.

Giriş, bir dizi 8 pozitif tamsayılar oluşan S ise, matematiksel bir şekilde, arzu edilen çıkış N tatmin herhangi bir sayıda söz konusu n 0 ve N arasında, x1, x2, x3, ..., x8 böyle vardır

x1+x2+...+x8=nandx1,x2,...,x8{0}S

Amacınız, giriş olarak 8 sayı alan bir program, bir işlev veya snippet yazmak ve yukarıda tanımlandığı gibi maksimum N değerini vermektir.

Kurallar:

  • Esnek I / O izinli, bu nedenle programınız girişi en uygun olan herhangi bir biçimde alabilir. Giriş numaralarının programınıza en uygun şekilde sıralandığını varsayabilirsiniz.
    • Programın giriş sırasına bağlı olup olmadığını lütfen cevabınıza yazınız
  • Giriş, 8 farklı pozitif tamsayı kümesidir (sıfır yok). Çıktı negatif olmayan bir tamsayıdır.
    • Giriş kümesinde 1 yoksa, programınız 0 vermelidir, çünkü 0 ile 0 arasındaki herhangi bir sayı gereksinimi karşılar.
    • Geçersiz giriş olması durumunda (set sıfır, negatif veya yinelenen sayılar içerir), programınız her şeyi yapabilir.
  • Standart boşluklar yasaktır.
  • Programınız birkaç dakika içinde modern bir bilgisayarda çalıştırılmalıdır.

Test durumları (çoğunlukla Şaşırtma ile ilgili sorunun altındaki cevaplardan alınmıştır):

[1, 2, 3, 4, 5, 6, 7, 8] => 64
[2, 3, 4, 5, 6, 7, 8, 9] => 0
[1, 3, 4, 5, 6, 7, 8, 9] => 72
[1, 2, 5, 13, 34, 89, 233, 610] => 1596
[1, 5, 16, 51, 130, 332, 471, 1082] => 2721
[1, 6, 20, 75, 175, 474, 756, 785] => 3356

Bu bir , yani her dilde en kısa program veya parçası kazanıyor!


1
Güzel bir bulmaca, ancak şahsen bazı daha fazla test vakasının gönderimimizi test etmek için yardımcı olacağını düşünüyorum.
Bay Xcoder,

Giriş boyutunu bir parametre yapmak daha iyi olmaz mıydı? Kaba kuvvet yaklaşımları, 8
Luis Mendo ile

1
@iBug O zamanki kural "modern bir bilgisayarda bir dakika içinde yayınlanmaya çalışılır" gibi bir şey. Bulanık, ancak genellikle yeterince iyi, çünkü kaba kuvvet ile verimli yaklaşımlar arasındaki fark çok büyük
Luis Mendo

1
Kaba kuvvet, "birkaç dakika" zaman sınırınızla mümkündür. Cevabımın biraz değiştirilmiş bir versiyonu, 7 yaşındaki dizüstü bilgisayarımdaki son test senaryosunu 1m20'de çalıştırıyor.
nimi

1
@Arnauld Clarified
iBug

Yanıtlar:



9

Jöle , 12 bayt

œċⱮ8Ẏ§ṢQJƑƤS

Çevrimiçi deneyin!

Telefonumdaki TIO'da tüm test durumlarını çalıştırmak ortalama olarak ~ 3.7 saniye sürüyor, bu yüzden şaşırtıcı şekilde oldukça hızlı.

açıklama

œċⱮ8Ẏ§ṢQJƑƤS     Monadic link / Full program.
  Ɱ8             Promote 8 to [1 ... 8] and for each value k:
œċ                    Generate all combinations of k elements from the list.
    Ẏ§           Tighten, then sum. Flatten to a 2D list then sum each.
      ṢQ         Sort the result and remove equal entries.
        JƑƤ      For each prefix of this list, return 1 if it is equal to its length range, 0 otherwise.
           S     Finally, sum the result (counts the 1's which is equivalent to what is being asked).

7

Haskell, 56 50 bayt

g c=[x|x<-[1..],all((/=x).sum)$mapM(0:)$c<$c]!!0-1

Çevrimiçi deneyin!

Bir kaba kuvvet yaklaşımı. 0Madeni para listesine ekleyin ve 8 toplama tüm kombinasyonlarını deneyin. nSeçimlerden herhangi birinin toplamına eşit olmayan ilk sayıyı bulun ve geri dönün n-1.

[1, 2, 5, 13, 34, 89, 233, 610]7 yaşındaki dizüstü bilgisayar donanımımda 5 milyona yakın bir zaman alıyor .

Düzenleme: -6 bayt @ Ørjan Johansen sayesinde

Daha kısa versiyon (-2 byte, yine @ Ørjan Johansen sayesinde)

Haskell, 48 bayt

g c=[x|x<-[1..],all((/=x).sum)$mapM(:0:c)c]!!0-1

ancak önemli ölçüde daha fazla bellek kullanıyor ve makinemde ağır çağrı alıyor ve "birkaç dakika içinde" bitmiyor.


1
Kullanabilirsiniz mapM(0:)$c<$c. (Aslında mapM(:0:c)c, çalışması gereken, ancak verilen test durumu için TIO'da zaman aşımına uğradı.)
Ørjan Johansen

4

Jöle , 9 bayt

Żœċ8§ḟ’$Ṃ

Çevrimiçi deneyin!

Nasıl çalışır

Żœċ8§ḟ’$Ṃ  Main link. Argument: A (array)

Ż          Prepend a 0 to A.
 œċ8       Take all combinations of length 8, with repetitions.
    §      Take the sum of each combination.
       $   Combine the two links to the left into a monadic chain.
      ’      Decrement all sums.
     ḟ       Filterfalse; keep only sums that do not appear in the decremented sums.
        Ṃ  Take the minimum.

2
Żṗ8§ḟ’$Ṃbir bayt kaydeder, ancak 8,5 dakika az sayılır mı emin değilim .
Dennis,


4

JavaScript (ES6),  100 88 80  76 bayt

Bu esasen kaba kuvvet arama, ancak hızlandırmak için budama ile geliştirilmiştir. TIO'da test durumları için ortalama yürütme süresi 1 saniyeye yakındır.

Giriş dizisinin en yüksekten en düşüğe doğru sıralandığını varsayar.

a=>[...Array(a[0]*9)].findIndex(g=(i=8,s)=>s*i>0?a.every(x=>g(i-1,s-x)):s)-1

Çevrimiçi deneyin!

Yorumlananlar

a =>                      // a[] = input array
  [...Array(a[0] * 9)]    // create an array of 9 * max(a) entries
  .findIndex(             // find the position of the first truthy result
    g = (i = 8, s) =>     // g = recursive function taking a counter i, initialized to 8
                          //     and a sum s, initialized to the position in the above array
      s * i > 0 ?         //   if s is positive and i is not equal to 0:
        a.every(x =>      //     for each value x in a[]:
          g(i - 1, s - x) //       do a recursive call with i - 1 and s - x
        )                 //     end of every()
      :                   //   else:
        s                 //     yield s (s = 0 means success and makes findIndex go on)
  ) - 1                   // end of findIndex(); decrement the result



2

Python 2 , 125 115 111 bayt

lambda c:sum(i==j for i,j in enumerate(sorted(set(map(sum,product([0]+c,repeat=8))))))-1
from itertools import*

Çevrimiçi deneyin!

Girdi olarak tam sayıların bir listesini bekler.

Açıklama:

# an anonymous function
lambda c:
                                                          # get all length-8 combinations of values, from (0,0,0,0,0,0,0,0) to (8,8,8,8,8,8,8,8)
                                                          # zero is added to ensure that combinations of fewer than 8 coins are represented Ex:(1,0,0,0,0,0,0,0)
                                                          product([0]+c,repeat=8)
                                                  # for each combination, sum the values
                                                  map(sum,.......................)
                                       # get unique values, then sort them smallest to largest
                                       sorted(set(................................))
             # for each index, value pair, return if the index is equal to the value
             i==j for i,j in enumerate(.............................................)
         # in Python arithmetic, False is 0 and True is 1. So, count how many items match their index.
         # Since zero was added to the list, there will always be one extra match (0==0). So offset by one.
         sum(........................................................................)-1
from itertools import*

2

Perl6, 65 63 41 bayt ( 39 37 karakter)

{@_=(0,|@_)X+(0,|@_)for ^3;($_ if $_==$++for @_.sort.unique)-1}

Çevrimiçi deneyin!

Bu, verilerini bir dizi olarak ileten anonim bir bloktur. (0,|@_)Bir eklemek için hızlı bir yoldur 0için @_ve iki kez bitti bile, daha hala biraz daha kısa @_.push: 0;sonra sonra boşluk gerekir ki _. Bu, 8 kombinasyon olduğu gerçeğine biraz peynir veren kaba kuvvet yaklaşımıdır. Çapraz eklemeden sonra, sıralı değerler için adsız bir liste oluşturulur. Matematik operatörleri ile listeler uzunluklarına göre değerlendirilir, böylelikle -1 çift görevi görür: 0 için hesaplar ve Int.

Bu onun tatlı zaman alabilir, ancak biri veya her ikisi değiştirerek yapabilirsiniz (0,|@_)için (0,|@_.unique)ilk önce foro ölçüde hızlandırılabilir. Birincisinin çok yavaş olduğunu düşünüyorsanız, skora +7 (çalışma süresi <60s) veya +14 (çalışma süresi <10s) ekler (bunu 60 saniye sonra zaman aşımını önlemek için bağlantılı kod için yaptım).

Düzenleme: Yorumlarda JoKing bunu iyileştirdi (aynı fikir, çapraz ekleme, ardından son ardışık sonucu döndür) şaşırtıcı bir 39 karaktere (41 bayt) döndü:

{(@_=@_ X+0,|@_)xx 3;first *+1@_,^∞}

Çevrimiçi deneyin!

Son tablolama işlemi 0'a ihtiyaç duymaz, sadece bir defada 0 eklemek zorunda kalarak birkaç bayttan tasarruf sağlar. xx 3Döngüsü taklit eden (yine 2'nin güç olan paralar peynir). firstAlt sonsuz listedeki ilk sayı döndürür 0..*( ^Infçok mümkündür, ancak uzayda tasarruf değil) olan +1çapraz katma listesinin bir üyesi değildir. Mayın gibi, yavaş, bu yüzden ekleyeceksiniz +7 bir için uniquebunu kılavuzlar için çok yavaş düşünüyorsanız ilk eşittir sonra.


1
48 bayt . Teknik olarak, uniquegerekli değildir, ama çok hızlandırır
Jo King

@JoKing, neden kullanmayı düşünmedim bilmiyorum xx. Nihai tabloyu set fonksiyonlarını kullanarak çok daha kısa bir şekilde yapmanın bir yolu olduğunu biliyordum, ama beynim çalışmıyordu.
user0721090601

xx 1Olmalıxx 3
Jo Kral

@JoKing düzeltildi. Ayrıca iki karakter (ancak bayt yok) kullanarak kaydedilebileceğini fark ettim^∞
user0721090601

Aslında, (1...*∉@_)-1kullanmak yerine bazı baytları kaydedebilirsiniz first, (ki burada kullandığımla aynı yöntem olduğunu farkettim )
Jo King

1

JavaScript (Node.js) , 171 145 115 bayt

f=(s,n=3)=>n?f(s=new Set(a=[0,...s]),n-1,a.map(m=>a.map(n=>s.add(m+n)))):Math.min(...[...s].filter(m=>!s.has(m+1)))

Çevrimiçi deneyin! @ Mark'ın Python Limanı 3 cevap. Firefox 30-57’de 108 bayt:

f=(s,n=3)=>n?f(new Set((for(n of s=[0,...s])for(m of s)n+m)),n-1):Math.min(...[...s].filter(m=>!s.has(m+1)))

1

Wolfram Dili (Mathematica) , 46 bayt

0//.x_/;Min[Tr/@FrobeniusSolve[#,x+1]]<9:>x+1&

Çevrimiçi deneyin!

Kaba kuvvet yaklaşımı: 8 madeni parayla ödenemeyecek bir değere ulaşana kadar tam sayıları kontrol eder. Çok, çok yavaş (tio zaman aşımına uğradı), ancak durumun doğru olduğundan oldukça eminim.


0

Temiz , 161 bayt

import StdEnv,Data.List
$l=:[1:_]#k=sort(nub(map sum(iter 8(concatMap(\[h:t]=[[e,h:t]\\e<-[0:l]|e>=h]))[[0]])))
=length(takeWhile((>=)1)(zipWith(-)(tl k)k))
$_=0

Çevrimiçi deneyin!

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.