Bei dieser Herausforderung erhalten Sie eine durch Kommas getrennte Liste von Gewichten als Eingabe, z
1,3,4,7,8,11
Und Sie müssen die kleinste Menge an Gewichten ausgeben, die zu diesem Satz hinzugefügt werden können. Zum Beispiel wäre die Ausgabe für diesen Satz
1,3,7
Weil Sie all diese Gewichte mit nur diesen drei darstellen könnten:
1 = 1
3 = 3
1+3 = 4
7 = 7
1+7 = 8
1+3+7 = 11
Es kann mehr als eine Lösung geben. Zum Beispiel Ihre Lösung für die Eingabe 1,2
könnte sein , 1,1
oder 1,2
. Solange die Mindestanzahl an Gewichten gefunden wird, die den Eingabesatz darstellen können, ist dies eine gültige Lösung.
Gewichte dürfen nicht mehr als einmal verwendet werden. Wenn Sie eine zweimal verwenden müssen, müssen Sie sie zweimal ausgeben. Dies ist beispielsweise 2,3
keine gültige Lösung für, 2,3,5,7
da Sie das nicht 2
zweimal verwenden können 2+2+3=7
.
Die Eingabe enthält garantiert keine doppelten Nummern.
Dies ist Code-Golf, so dass der kürzeste Code nach Zeichenanzahl gewinnt.
Der Netzwerkzugriff ist verboten (also keine Ihrer "cleveren" wget
Lösungen @JohannesKuhn Husten Husten );)
Einfachste Fälle:
1,5,6,9,10,14,15 => 1,5,9
7,14,15,21,22,29 => 7,14,15
4,5,6,7,9,10,11,12,13,15,16,18 => 4,5,6,7
2,3,5,7 => 2,2,3 or 2,3,7
Und einige schwierigere:
10,16,19,23,26,27,30,37,41,43,44,46,50,53,57,60,61,64,68,71,77,80,84,87
=> 3,7,16,27,34
20,30,36,50,56,63,66,73,79,86
=> 7,13,23,43
27,35,44,46,51,53,55,60,63,64,68,69,72,77,79,81,86,88,90,95,97,105,106,114,123,132
=> 9,18,26,37,42
7,7,7,8
oben) zulässt , was die Komplexität um ein Vielfaches erhöht.n
Eingangsgewichte gibt undm
das größte ist, alle Teilsequenzen von aufzählen(1..m)
und für jede Teilsequenz jede Kombination von 1 undn
Instanzen von jedem aufzählen Element der Sequenz.)Antworten:
Mathematica
8075Update: Unten finden Sie ein Update zu Doorknobs herausforderndem letzten Test, der am 5. November hinzugefügt wurde
Dies besteht alle bis auf den letzten Test. Es wird jedoch nicht versucht, eine Ziffer mehr als einmal zu verwenden. Und es wird nur nach Lösungen gesucht, die Teilmengen des größeren Datensatzes sind.
Die Funktion generiert alle Teilmengen des Eingabedatensatzes und testet dann, welche Teilmengen zum Erstellen des vollständigen Satzes verwendet werden können. Nachdem die realisierbaren Teilmengen gefunden wurden, werden die kleinsten Mengen ausgewählt.
Tests
Aktualisieren
Im Folgenden werde ich eine erste Analyse bereitstellen, die Ihnen dabei helfen kann, eine Lösung zu finden.
Die Daten:
Anders als beim früheren Ansatz möchten wir im Lösungssatz Zahlen berücksichtigen, die NICHT im Datensatz enthalten sind.
Der Ansatz nutzt absolute Unterschiede zwischen Zahlenpaaren im Datensatz.
Schauen wir uns an, wie oft jeder Unterschied auftritt. Wir werden nur die ersten 8 Fälle behandeln, beginnend mit dem häufigsten Unterschied.
14 Paare unterschieden sich um 7; 13 Paare unterschieden sich um 27 und so weiter.
Testen wir nun Teilmengen, die mit {Differenz1}, {Differenz1, Differenz2} usw. beginnen, bis wir hoffentlich alle ursprünglichen Elemente im Datensatz berücksichtigen können.
h
zeigt die Zahlen aus der ursprünglichen Menge an, die nicht durch Zusammensetzen von Summen aus der Teilmenge konstruiert werden können.Beim fünften Versuch gibt es noch 10 Elemente, die nicht aus {7, 27, 34, 3, 20} gebildet werden können:
Beim nächsten Versuch werden jedoch alle Nummern des Datensatzes berücksichtigt:
Dies ist immer noch nicht so wirtschaftlich wie {3,7,16,27,34}, aber es ist nah.
Es sind noch einige zusätzliche Dinge zu berücksichtigen.
Dies sind mehr Probleme, als ich im Moment behandeln kann. Aber ich hoffe, es wirft ein Licht auf diese sehr interessante Herausforderung.
quelle
w
wiederholt wird, funktioniert dieselbe Lösung, bei der eines derw
s geändert wurde,2 * w
auch, da Sie die Lösung2 * w
überall verwenden können, wo Sie siew + w
zuvor verwendet haben. Dies kann wiederholt werden, bis die Lösung keine Wiederholungen mehr aufweist. Daher müssen Sie nicht versuchen, Wiederholungen zu verwenden.s=Subsets;
sich aus der FunktionRuby 289
Dies ist eine direkte Aufzählung, sodass nur minimale Lösungen erzielt werden. Es kann jedoch Jahre - möglicherweise Lichtjahre - dauern, bis einige Probleme gelöst sind. Alle "einfachsten Fälle" lösen sich in höchstens wenigen Sekunden (obwohl ich für den 3. bzw. 5. Fall 7,8,14 und 1,2,4 erhalten habe). Tricky # 2 wurde in ungefähr 3 Stunden gelöst, aber die anderen beiden sind einfach zu groß für die Aufzählung, zumindest für die Art und Weise, wie ich es gemacht habe.
Ein Array mit einer Größe
n
, die das angegebene Array durch Summieren von Teilmengen seiner Elemente generiert, hat eine minimale Größe, wenn gezeigt werden kann, dass es kein Array mit einer Größe gibt< n
, die dies tut. Ich kann keinen anderen Weg sehen, um die Optimalität zu beweisen, also beginne ich die Aufzählung mit Teilmengen der Größem
, wobeim
es sich um eine bekannte Untergrenze handelt, und erhöhe dann die Größe auf,m+1
nachdem ich Teilmengen der Größe aufgezähltm
und gezeigt habe, dass sie keine dieser "Spannen" der angegebenen umfassen Array und so weiter, bis ich ein Optimum finde. Wenn ich alle Teilmengen bis zur Größe n aufgelistet habe, könnte ich natürlich eine Heuristik für die Größe n + 1 verwenden. Wenn ich also ein übergreifendes Array dieser Größe finden würde, würde ich wissen, dass es optimal ist. Kann jemand einen alternativen Weg vorschlagen, um zu beweisen, dass eine Lösung im allgemeinen Fall optimal ist?Ich habe einige optionale Überprüfungen hinzugefügt, um einige Kombinationen frühzeitig zu eliminieren. Das Entfernen dieser Überprüfungen würde 87 Zeichen sparen. Sie sind wie folgt (
a
ist das gegebene Array):n
kann höchstens2^n-1
unterschiedliche positive Zahlen erzeugen . daher2^n-1 >= a.size
odern >= log2(a.size).ceil
(die "Untergrenze", auf die ich oben Bezug genommen habe).b
einer Größe generiert,n
kann ausgeschlossen werden, wenn:b.min > a.min
sum of elements of b < a.max
oderb.max < v
, wov = a.max.to_f/n+(n-1).to_f/2.ceil
(to_f
Umwandlung in Float).Die letzte davon, die zuerst überprüft wird, implementiert
Hinweis
v
ist für alle Generator-Arrays der Größe konstantn
.Ich habe auch die sehr hilfreiche Beobachtung von @ cardboard_box verwendet, dass keine Duplikate im generierenden Array berücksichtigt werden müssen.
In meinem Code
erzeugt alle Kombinationen der Zahlen 1 bis
a.max
, dien
gleichzeitig (woa.max = a.last = a[-1]
) genommen werden. Für jede Kombinationb
:Füllt einen Hash
h
mit allen Zahlen, die Summen über nicht leere Teilmengen von sindb
. Die Hash-Schlüssel sind diese Zahlen; Die Werte sind beliebig. (Ich habe letzteres auf Null gesetzt.)prüft, ob jedes Element des angegebenen Arrays
a
ein Schlüssel im Hash ist (h[e] != nil
oder nurh[e]
).Annehmen
Dann iterieren wir über den Bereich:
Die binäre Darstellung jeder Zahl in diesem Bereich wird verwendet, um die Elemente der
b
Summe zu erstechen . Fürj = 3
(j
als Bereichsindex),Der Code:
quelle