Kod Nugatları


18

Kod Nugatları

O var öyle varsayımsal durum Cuma akşamı ve favori hobi katılmaya zamanki golf arkadaşları üzerinde davet ediyorum: Kod golf. Bununla birlikte, bu beyninizi boşaltan bir görev olduğu için, grup için biraz beyin yemi almanız gerekir, böylece kodunuzdan mümkün olduğunca golf oynayabilirsiniz.

Şimdi, herkesin en sevdiği atıştırmalık tavuk nugget'ları, ancak bir sorun var: Herkesin ihtiyaçlarını karşılayan tek bir paket yok. Bu nedenle, zaten golf havasında olduğunuz için, herkesin Nugget ihtiyaçlarını karşılamak için tam olarak hangi paketleri satın almanız gerektiğini anlayan bir program oluşturmaya karar verdiniz.

Tavuk nugget paket boyutları her yerdedir ve dünyanın neresinde yaşadığınıza bağlı olarak standart boyutlar da değişir. Ancak, en yakın [külçe servisi yapan yer] aşağıdaki boyutlarda külçe paketlerini stoklar:

4, 6, 9, 10, 20, 40

Artık belirli külçe kombinasyonlarını sipariş edemeyeceğinizi fark edebilirsiniz. Örneğin, tam olarak 11eşit bir kombinasyon olmadığından , külçeler mümkün değildir 11. Ancak, 431 paket 20, 1 paket 10, 1 paket 9ve 1 paket elde ederek 4,

20 + 10 + 9 + 4 = 43 (597)

burada 597her bir terim birbirine kare ve ilave edilir (ipucu: en iyi çözüm en yüksek değer olarak bulunmaktadır) . Tabii ki yapmanın başka yolları da var 43, ama bildiğiniz gibi, paket başına daha fazla külçe, külçe başına daha ucuz oluyor. Bu nedenle, maliyetinizi en aza indirmek için en az sayıda paketi ve en büyük miktarlarda ideal olarak satın almak istersiniz.

Görev

Her bir kişinin gereksinimlerine karşılık gelen tamsayıların listesini alan bir program veya işlev oluşturmalısınız . Daha sonra tavuk külçelerini satın almak için en uygun maliyetli α siparişini hesaplamalı ve yazdırmalısınız . En uygun maliyetli α sırası, her bir miktarın karelerinin toplamının en yüksek olduğu kombinasyondur. Mükemmel Nuggets satın almak için hiçbir yolu yoksa, sen gerekir yazdırmak gibi bir falsy değer , , veya kendi dilinizde durumuna göre.0FalseImpossible!

Örnek G / Ç:

[2 7 12 4 15 3] => [20 10 9 4]
     1, 1, 2, 1 => False
  6 5 5 5 5 5 9 => 40
      [6, 4, 9] => 9 10
              1 => 0
            199 => 40, 40, 40, 40, 20, 10, 9
              2 => Impossible!

İşte ilk 400 için ideal çözümlerin listesi. Bunların sizin nasıl olmasını beklediğimi biçimlendirilmemiş, her tuplebiri formda (N lots of M).

kurallar

  1. Standart boşluklar yok.
  2. FrobeniusSolveMathematica gibi, görevin tamamını veya çoğunu yerine getiren yerleşik işlevler kullanılmaz .

α - Bunu bir örnekle açıklığa kavuşturmak için, 43 yaparak da yapabilirsiniz 4 + 6 + 6 + 9 + 9 + 9 = 43 (319), ancak kareler toplamı girişte belirttiğim kombinasyondan daha az olduğu için bu uygun olmaz ve dolayısıyla yanlış bir çıktı olmaz. Esasen, daha yüksek kareler = daha düşük maliyet = en düşük maliyetli.


Herhangi bir zaman / bellek sınırı var mı?
Dennis

@Dennis Zaman veya bellek sınırı yoktur.
Kade

4
Aslında Perşembe.
mbomb007

4
@ mbomb007 Zeki gözlem: P Giriş ayarladım.
Kade

2
Ben bir şekilde tavuk mcnugget teoremi kullanmak GEREKİR ...
Stretch Maniac

Yanıtlar:


7

Pyth, 26 25 bayt

e+Zo.aNf!-TCM"  
("./sQ

Bazı yazdırılamaz karakterler olduğuna dikkat edin. Çevrimiçi deneyin: Gösteri . Oldukça yavaş (ama 26 baytlık çözümüm kadar yavaş değil).

Açıklama:

                          implicit: Q = input list
                     sQ   sum(Q)
                   ./     generate all integer partitions
       f                  filter for partitions T, which satisfy:
             "   ("          string containing chars with the ASCII-values of 4,6,9,10,20,40
           CM                convert each char to the ASCII-value
         -T                  remove this numbers from T
        !                    and check, if the resulting list is empty
    o                      order the remaining subsets N by:
     .aN                      the vector length of N (sqrt of sum of squares)
  +Z                       insert 0 at the beginning
 e                         print the last element

Pyth, 32 bayt

e+Zo.aNfqsTsQysm*]d/sQdCM"  
(

Bazı yazdırılamaz karakterler olduğuna dikkat edin. Çevrimiçi deneyin: Gösteri Bu sürüm çok daha hızlı. Giriş çözümünü [6,7,8]yaklaşık bir saniye içinde ve giriş çözümünü [30]yaklaşık 90 saniye içinde bulur .

Açıklama:

                                 implicit: Q = input list
                          "...(  the string containing chars with the ASCII-values of 4,6,9,10,20,40
                        CM       convert each char to the ASCII-value
                m                map each number d to:
                  ]d                create the list [d]
                 *  /sQd            and repeat it sum(Q)/d times
               s                 unfold
              y                  generate all subsets
        f                        filter for subsets T, which satisfy:
         qsTsQ                      sum(Q) == sum(T)
    o                            order the remaining subsets N by:
     .aN                            the vector length of N (sqrt of sum of squares)
  +Z                             insert 0 at the beginning
 e                               print the last element

Neden sadece toplamdan ziyade karelerin toplamının sqrt'ına göre?
mbomb007

1
@ mbomb007 Çünkü önemli değil. A> b ise, sqrt (a)> sqrt (b) ve tersi. Ve .ayöntemi kullanmak, kareleme ve toplamaya göre daha kısadır s^R2.
Jakube

5

Perl, 175 153

sub f{my$n=$_[0];if(!$n){return 1;}foreach$o(40,20,9,10,6,4){if($n>=$o&&f($n-$o)){print"$o ";return 1;}}return 0;}$n+=$_ for@ARGV;if(!f($n)){print":(";}

Girdilerini program argümanlarından alır. Mükemmel bir çözüm bulamazsa a :( yazdırır .

Kodlanmamış Kod:

sub f
{
    my $n = $_[0];
    if(!$n)
    {
        return 1;
    }
    foreach $o(40,20,9,10,6,4)
    {
        if($n>=$o&&f($n-$o))
        {
            print "$o ";
            return 1;
        }
    }
    return 0;
}

$n += $_ for @ARGV;
if(!f($n))
{
    print ":(";
}

Not: Bu muhtemelen 10 dakika sürmeyen ilk giriştir 1 2;)

Buradan kontrol edin.


Şimdiye kadarki en hızlı program gibi görünen şey için tebrikler! Referans programımdan da daha hızlı olabilir: P İnsanların çıktıyı görebilmesi için yayınınızın altına bir ideone bağlantısı ekledim.
Kade

Kodunuz yanlış çıktı üretebilir. Giriş 18yazdırılmalı 9 9, yazdırılmamalıdır 4 4 10.
Dennis

Başka yanlış çıktılar da var. Yanılmıyorsam varsa, sırasını değiştirerek hepsini düzeltebilir 9ve 10.
Dennis

@Dennis Teşekkürler, düzelttim!
Thomas Oltmann

3

CJam, 45 29 28 bayt

q~:+_[40K9A6Z)U]m*_::+@#=0-p

Bu yaklaşımın çok yavaş ve bellek yoğun olduğunu unutmayın.

CJam yorumlayıcısında çevrimiçi deneyin .

5 baytlık maliyetle önemli ölçüde hızlandırılabilir:

q~:+_40/4+[40K9A6Z)U]m*_::+@#=0-p

Girdi toplamında karmaşıklık hala üsteldir, ancak bu, çevrimiçi yorumlayıcı ile 159'a kadar ve birkaç saniye içinde Java yorumlayıcıyla 199'a kadar test durumlarını ele almalıdır.

CJam yorumlayıcısında çevrimiçi deneyin .

Fikir

Optimal bir alım (kareler maksimal toplamı) sayısı kadar olan geçerli bir alım (külçelerin doğru sayısı) 40 'sayısı kadar, daha sonra mümkün olduğu kadar s , 20 ' mümkün s, daha sonra bir çok şekilde 9 '(örneğin, mümkün olduğunca s 9 9olan tercih fazla 10 4 4) ve benzeri için 10 's, 6 ' nın ve 4 'ler.

Bu yaklaşımda, [40 20 9 10 6 4 0] dizisinin N kopyasının Kartezyen ürününü üretiyoruz , burada N istenen sayıda külçe sayısıdır. N , yapmamız gereken satın alma sayısı için (kötü) bir üst sınırdır. Kodun hızlandırılmış versiyonunda, bunun yerine N / 40 + 4 kullanıyoruz.

Dizinin nasıl sıralandığından dolayı, Kartezyen ürün [40 ... 40] vektörü ile başlar ve [0 ... 0] vektörü ile sona erer . Doğru toplamı olan (aynı zamanda en uygun kareler toplamına sahip olacak) ilk vektörün dizinini hesaplar, karşılık gelen dizi elemanını alırız, yer tutucu olarak görev yapan sıfırları kaldırır ve sonucu yazdırırız.

Hiçbir vektör bulunamazsa, dizin -1 olur , bu nedenle boş bir dizi basacak olan [0 ... 0] değerini alırız .

kod

q~                            e# Read from STDIN and evaluate the input.
  :+                          e# Push N, the sum of all elements of the resulting array.
     [40K9A6Z)U]              e# Push B := [40 20 9 10 6 4 0].
    _           m*            e# Push B**N, the array of all vectors of dimension N
                              e# and coordinates in B.
                  _::+        e# Copy and replace each vector by its sum.
                      @#      e# Get the first index of N.
                        =     e# Retrieve the corresponding element.
                         0-p  e# Remove 0's and print.

Bu, çözümü elle çalıştırmanın kodun bitmesine izin vermekten daha hızlı olacağı birkaç durumdan biri olabilir .. ne olursa olsun güzel iş :)
Kade

2

Julia, 126 bayt

r->(t=filter(i->all(j->j[4,6,9,10,20,40],i),partitions(sum(r)));show(!isempty(t)&&collect(t)[indmax(map(k->sum(k.^2),t))]))

Bu, bir diziyi giriş olarak kabul eden adsız bir işlev oluşturur ve bir çözümün bulunup bulunmamasına bağlı olarak STDOUT'a bir dizi veya boole yazdırır. Bunu aramak için bir ad verin, örn f=n->....

Ungolfed + açıklaması:

function f(r)
    # Nugget pack sizes
    packs = [4, 6, 9, 10, 20, 40]

    # Filter the set of arrays which sum to the required number of nuggets
    # to those for which each element is a nugget pack
    t = filter(i -> all(j -> jpacks, i), partitions(sum(r)))

    # Print the boolean false if t is empty, otherwise print the array of
    # necessary nugget packs for which the sum of squares is maximal
    show(!isempty(t) && collect(t)[indmax(map(k -> sum(k.^2), t))])
end

Örnekler:

julia> f([1])
false

julia> f([2,7,12,4,15,3])
[20,10,9,4]

1

Python 3- 265 karakter

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,9):
 for j in range(6*f):
  for x in i.combinations((4,6,9,10,20,40,)*f,j+1):
   if sum(n)==sum(x):m.append(x)
if m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

Boşluk gösteriliyor:

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,5):
 for j in range(6*f):
\tfor x in i.combinations((4,6,9,10,20,40,)*f,j+1):
\t if sum(n)==sum(x):m.append(x)
\t\tif m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

Tüm test senaryolarını geçer

Not: Bunun tüm vakaları geçip geçmeyeceğini bilmiyorum çünkü çok yavaş ... Ama olmalı ...


Şu an bununla ilgili hiçbir şey yanlış görünmüyor, test edip göreceğim. Eve geldiğimde, Gist'teki listeyi oluşturmak için kullandığım bir referans, ungolfed programı ekleyeceğim. Zamanlama olmasa da, tüm vakalar için 8-12 dakikalık bir süre içinde bir yere geldiğine inanıyorum.
Kade

@ Vioz- Brilliant! : D
Beta Çürümesi

Yanlış yaptığım anlaşılıyor, 36'yı test ettikten sonra bir MemoryError'a girmeden önce yaklaşık 40 milyon kombinasyondan (40,007,602 tam olarak) geçiyor. Bu, sadece 4GB belleğe sahip olduğu için iş makinemin bir sınırlaması olabilir.
Kade

@ Vioz- Hm ... Telefonumda test yapmaya devam etmek benim için umutsuz ...
Beta Decay

1
@undergroundmonorail Yalnızca bir kez kullanıyorsanız, <= 4 karakter için düz bir içe aktarma daha iyidir (5 mola bile). Ama bir kereden fazla kullanıyorsanız, o from blah import*zaman her zaman en iyisidir. Yukarıda düşünebildiğim tek istisna , aslında yararlı importolan akla gelen tek zaman olan birden fazla s'niz varsa as.
Sp3000

1

JavaScript, 261 256 261

d="length";function g(a){for(z=y=0;y<a[d];z+=+a[y++]);return z}x=[40,20,10,9,6,4];l=prompt().split(",");o=g(l);p=[];for(i=0;i<x[d];i++)r=g(p),s=r+x[i],(s<o-3||s==o)&&p.push(x[i]),(i==x[d]-1||40<o-r)&&r+x[i]<o-3&&(i=-1,0==i||o-r<p[p[d]-1]&&p.pop());g(p)==o&&p||0

Bunun iyi olup olmadığından emin değilim, işe yarıyor gibi görünüyor ama kesinlikle bir şeyleri kaçırıyorum.

O kadar yavaş olsa olmak görünmüyor 123456o verir [40 x 3086, 10, 6]neredeyse anında.

Açıklama:

Nugget boyutları üzerinde yineleme (en büyüğü)

  • Yığın toplamı ve külçe boyutu hedefin altındaysa - 3 -> bir yığının üzerine itin
  • 40'tan fazla kaldıysa -> döngü sayacını sıfırlayın
  • Son külçe boyutuna ulaşıldığında yığının toplamı hedeften fazlaysa -> son öğeyi aç, döngü sayacını sıfırla
  • Yığın toplamı toplanırsa, döndürün, aksi takdirde 0 döndürün

199 için | 1 inşa edilen yığın şöyle görünür

i | stack
0   [40]
0   [40, 40]
0   [40, 40, 40]
0   [40, 40, 40, 40]
0   [40, 40, 40, 40]
1   [40, 40, 40, 40, 20]
2   [40, 40, 40, 40, 20, 10]
3   [40, 40, 40, 40, 20, 10, 9]
4   [40, 40, 40, 40, 20, 10, 9]
5   [40, 40, 40, 40, 20, 10, 9]
==> [40, 40, 40, 40, 20, 10, 9]

1 için

i | stack
0   []
1   []
2   []
3   []
4   []
5   []
==> 0

1
Yaklaşımınız hedefe ulaşılıp ulaşılamayacağını kontrol etmiyor gibi görünüyor. 11baskılar [6]ve 18baskılar [10, 4].
Dennis

@Dennis Hey, bunu belirttiğin için teşekkürler. Dün gece geç oldu. 5 karakter için düzeltildi. 18 yazdırdım [10,4]çünkü bir çift ebeveynim eksikti. Kontrol gerçekten yanlıştı, ben sadece sonuç kümesinde en az bir eleman olup olmadığını kontrol ettim, doğru bir şekilde özetliyorsa değil. Orada ne düşündüğümü bilmiyorum
C5H8NNaO4
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.