Nuggets of Code

18

Nuggets of Code

Es ist eine hypothetische Situation, in der es Freitagabend ist und Sie über die üblichen Golfkameraden eingeladen haben, an Ihrem Lieblingshobby teilzunehmen: Code-Golf. Da dies jedoch eine hirntreibende Aufgabe ist, müssen Sie etwas Gehirnfutter für die Gruppe aufheben, damit Sie so viel wie möglich aus Ihrem Code heraus Golf spielen können.

Heutzutage sind Hühnernuggets die beliebtesten Snacks für jedermann, aber es gibt ein Problem: Es gibt keine einzige Packung, die alle Bedürfnisse abdeckt. Da Sie also bereits in Golfstimmung sind, entscheiden Sie sich für ein Programm, das genau herausfindet, welche Packs Sie kaufen müssen, um die Nugget-Bedürfnisse aller zu decken.

Hühnernugget-Packungsgrößen gibt es überall, und je nachdem, wo Sie auf der Welt leben, ändern sich auch die Standardgrößen. Der nächstgelegene [Ort, an dem Nuggets serviert werden] verfügt jedoch über die folgenden Größen von Nugget-Paketen:

4, 6, 9, 10, 20, 40

Jetzt stellen Sie möglicherweise fest, dass Sie bestimmte Kombinationen von Nuggets nicht bestellen können. Zum Beispiel sind 11Nuggets nicht möglich, da es keine 11genau gleiche Kombination gibt . Sie können jedoch 431 Packung mit 20, 1 Packung mit 10, 1 Packung mit 9und 1 Packung mit 4,

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

wo 597wird jeder Term quadriert und addiert (Hinweis: die optimale Lösung hat dies als höchsten Wert) . Es gibt natürlich auch andere Herstellungsmethoden 43, aber wie Sie wissen, wird die Herstellung eines Nuggets umso billiger, je mehr Nuggets es pro Packung gibt. Sie möchten also im Idealfall die geringste Anzahl von Packungen und die größten Mengen kaufen, um Ihre Kosten zu minimieren.

Die Aufgabe

Sie sollten ein Programm oder eine Funktion erstellen, die eine Liste von ganzen Zahlen enthält, die den Anforderungen jeder Person entsprechen. Sie sollten dann die kostengünstigste α- Bestellung berechnen und ausdrucken , um die Hühnernuggets zu kaufen. Die kostengünstigste α- Bestellung ist die Kombination, bei der die Summe der Quadrate jeder Größe die höchste ist. Wenn es absolut keine Möglichkeit , die Nuggets zu kaufen ist perfekt, müssen Sie drucken einen falsy Wert wie , , oder was auch immer in Ihrer Sprache zur Verfügung steht.0FalseImpossible!

Beispiel I / O:

[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!

Hier ist die Liste der idealen Lösungen für den ersten 400. Hinweis diese nicht formatiert , wie ich würde erwarten , dass bei Ihnen sein, die jeweils tuplein Form (N lots of M).

Regeln

  1. Keine Standardlücken.
  2. Keine Verwendung von integrierten Funktionen, die die gesamte Aufgabe oder den größten Teil der Aufgabe erledigen, wie FrobeniusSolvein Mathematica.

α - Um dies an einem Beispiel zu verdeutlichen, könnten Sie auch 43 machen 4 + 6 + 6 + 9 + 9 + 9 = 43 (319), aber dies wäre nicht optimal und daher eine falsche Ausgabe, da die Summe der Quadrate kleiner ist als die Kombination, die ich in der Einleitung notiert habe. Im Wesentlichen ist eine höhere Quadratsumme = niedrigere Kosten = die kostengünstigste.

Kade
quelle
Gibt es Zeit- / Speicherbeschränkungen?
Dennis
@Dennis Es gibt keine Zeit- oder Speicherbeschränkungen.
Kade
4
Es ist eigentlich Donnerstag.
mbomb007
4
@ mbomb007 Raffinierte Beobachtung: P Ich habe das Intro angepasst.
Kade,
2
Ich MUSS das Chicken McNugget-Theorem irgendwie benutzen ...
Stretch Maniac

Antworten:

7

Pyth, 26 25 Bytes

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

Beachten Sie, dass einige nicht druckbare Zeichen vorhanden sind. Probieren Sie es online aus: Demonstration . Es ist ziemlich langsam (aber nicht so langsam wie meine 26-Byte-Lösung).

Erläuterung:

                          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 Bytes

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

Beachten Sie, dass einige nicht druckbare Zeichen vorhanden sind. Probieren Sie es online aus: Demonstration Diese Version ist viel schneller. Es findet die Lösung für die Eingabe [6,7,8]in ungefähr einer Sekunde und die Lösung für die Eingabe [30]in ungefähr 90 Sekunden.

Erläuterung:

                                 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
Jakube
quelle
Warum ist es nicht nur die Summe, sondern die Summe der Quadrate?
mbomb007
1
@ mbomb007 Weil es egal ist. Wenn a> b, dann sqrt (a)> sqrt (b) und umgekehrt. Und die .aMethode ist kürzer als Quadrieren und Summieren 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":(";}

Nimmt seine Eingabe von den Programmargumenten. Gibt ein :( aus, wenn keine perfekte Lösung gefunden werden kann.

Ungolfed Code:

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 ":(";
}

PS: Dies ist wahrscheinlich der erste Eintrag, für den 10 Minuten vergehen 1 2;)

Schau es dir hier an.

Thomas Oltmann
quelle
Herzlichen Glückwunsch zu dem scheinbar schnellsten Programm! Möglicherweise ist es auch schneller als mein Referenzprogramm: P Ich habe einen Ideone-Link am Ende Ihres Posts hinzugefügt, damit die Benutzer die Ausgabe sehen können.
Kade,
Ihr Code kann zu einer falschen Ausgabe führen. Die Eingabe 18sollte gedruckt werden 9 9, nicht 4 4 10.
Dennis
Es gibt auch andere falsche Ausgaben. Wenn ich mich nicht irre, können Sie alle Probleme beheben, indem Sie die Reihenfolge von 9und vertauschen 10.
Dennis
@ Tennis Danke, behoben!
Thomas Oltmann
3

CJam, 45 29 28 Bytes

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

Beachten Sie, dass dieser Ansatz sehr langsam und speicherintensiv ist.

Probieren Sie es online im CJam-Interpreter aus .

Es kann auf Kosten von 5 Bytes erheblich beschleunigt werden:

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

Die Komplexität ist in der Summe der Eingaben immer noch exponentiell, dies sollte jedoch in wenigen Sekunden Testfälle bis zu 159 mit dem Online-Interpreter und bis zu 199 mit dem Java-Interpreter bewältigen.

Probieren Sie es online im CJam-Interpreter aus .

Idee

Ein optimaler Kauf (maximale Summe der Quadrate) ist ein gültiger Kauf (richtige Anzahl von Nuggets) , die so viele hat 40 sind wie möglich, dann , wie viele 20 ist wie möglich, so viele 9 ist wie möglich ( zum Beispiel 9 9ist vorzuziehen 10 4 4) und so weiter für 10 's, 6 ' s und 4 's.

In diesem Ansatz erzeugen wir das kartesische Produkt von N Kopien des Arrays [40 20 9 10 6 4 0] , wobei N die gewünschte Anzahl von Nuggets ist. N ist eine (schlechte) Obergrenze für die Anzahl der Käufe, die wir tätigen müssen. In der beschleunigten Version des Codes verwenden wir stattdessen N / 40 + 4 .

Aufgrund der Anordnung des Arrays beginnt das kartesische Produkt mit dem Vektor [40 ... 40] und endet mit dem Vektor [0 ... 0] . Wir berechnen den Index des ersten Vektors mit der korrekten Summe (der auch die optimale Quadratsumme enthält), rufen das entsprechende Array-Element ab, entfernen die als Platzhalter dienenden Nullen und drucken das Ergebnis.

Wenn kein Vektor gefunden werden konnte, ist der Index -1. Daher rufen wir [0 ... 0] ab , wodurch stattdessen ein leeres Array ausgegeben wird.

Code

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.
Dennis
quelle
Dies kann eine der wenigen Situationen sein, in denen das Ausarbeiten der Lösung von Hand schneller ist, als das Beenden des Codes. Trotzdem gute Arbeit :)
Kade
2

Julia, 126 Bytes

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

Dadurch wird eine unbenannte Funktion erstellt, die ein Array als Eingabe akzeptiert und ein Array oder einen Booleschen Wert an STDOUT ausgibt, je nachdem, ob eine Lösung vorhanden ist. Um es zu nennen, geben Sie ihm einen Namen, z f=n->....

Ungolfed + Erklärung:

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

Beispiele:

julia> f([1])
false

julia> f([2,7,12,4,15,3])
[20,10,9,4]
Alex A.
quelle
1

Python 3 - 265 Zeichen

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)

Abstand anzeigen:

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)

Besteht alle Testfälle

Hinweis: Ich weiß nicht, ob dies alle Fälle bestehen wird, weil es so langsam ist ... Aber es sollte ...

Beta-Zerfall
quelle
Im Moment sieht nichts falsch aus, ich werde es testen und sehen. Sobald ich nach Hause komme, füge ich ein Referenzprogramm ohne Golf hinzu, mit dem ich die Liste im Gist erstellt habe. Obwohl ich kein Timing hatte, glaube ich, dass es in allen Fällen zwischen 8 und 12 Minuten dauerte.
Kade,
@ Vioz- Genial! : D
Beta Decay
Es sieht so aus, als ob ich mich irre, nachdem ich 36 getestet habe, werden ungefähr 40 Millionen Kombinationen (genauer gesagt 40.007.602) durchlaufen, bevor ein MemoryError ausgeführt wird. Dies könnte jedoch eine Einschränkung meiner Arbeitsmaschine sein, da sie nur 4 GB Arbeitsspeicher hat.
Kade,
@ Vioz- Hm ... Nun, es ist hoffnungslos für mich, weiter auf meinem Handy zu testen ...
Beta-Zerfall
1
@undergroundmonorail Wenn Sie es nur einmal verwenden, ist ein direkter Import für <= 4 Zeichen besser (5 Break Even). Aber wenn Sie es mehr als einmal verwenden, from blah import*ist es immer am besten. Die einzige Ausnahme, an die ich denken kann, ist, wenn Sie mehrere imports haben. Dies ist die einzige Zeit, die mir in den Sinn kommt, wo dies astatsächlich nützlich ist.
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

Ich bin mir nicht sicher, ob das in Ordnung ist, es scheint zu funktionieren, aber mir fehlen sicherlich Dinge.

Es scheint jedoch nicht langsam zu sein, bis 123456es [40 x 3086, 10, 6]fast sofort ausgibt .

Erläuterung:

Durchlaufen der Nugget-Größen (größte zuerst)

  • Wenn die Summe des Stapels plus der Nugget-Größe kleiner als das Ziel ist - 3 -> schieben Sie es auf einen Stapel
  • Wenn mehr als 40 übrig sind -> setzen Sie den Schleifenzähler zurück
  • Wenn die Summe des Stapels größer als das Ziel ist, als die letzte Nugget-Größe erreicht wurde, setzen Sie den Schleifenzähler zurück
  • Wenn sich die Summe des Stapels summiert, geben Sie ihn zurück, andernfalls geben Sie 0 zurück

Für 199 | 1 sieht der gebaute Stack so aus

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]

Für 1

i | stack
0   []
1   []
2   []
3   []
4   []
5   []
==> 0
C5H8NNaO4
quelle
1
Ihr Ansatz scheint nicht zu prüfen, ob das Ziel erreicht werden kann. 11druckt [6]und 18druckt [10, 4].
Dennis
@Dennis Hey, danke, dass du darauf hingewiesen hast. Es war gestern eine späte Nacht. Behoben für 5 Zeichen. 18 gedruckt, [10,4]weil mir ein Paar Eltern fehlte. Die Prüfung war in der Tat falsch. Ich habe nur geprüft, ob mindestens ein Element in der Ergebnismenge vorhanden ist, nicht, ob es richtig zusammengefasst wurde. Ich weiß nicht, was ich dort gedacht habe
C5H8NNaO4