Die Lösung dieses Problems wurde im Internet millionenfach gegeben. Das Problem heißt Das Münzwechselproblem . Lösungen finden Sie unter http://rosettacode.org/wiki/Count_the_coins und ein mathematisches Modell davon unter http://jaqm.ro/issues/volume-5,issue-2/pdfs/patterson_harmel.pdf (oder bei Google Coin Change) Problem ).
Interessant ist übrigens die Scala-Lösung von Tsagadai. In diesem Beispiel wird entweder 1 oder 0 erzeugt. Als Nebeneffekt werden alle möglichen Lösungen auf der Konsole aufgelistet. Es zeigt die Lösung an, macht sie jedoch in keiner Weise verwendbar.
Um so nützlich wie möglich zu sein, sollte der Code a zurückgeben List[List[Int]]
, damit die Anzahl der Lösungen (Länge der Liste der Listen), die "beste" Lösung (die kürzeste Liste) oder alle möglichen Lösungen ermittelt werden können.
Hier ist ein Beispiel. Es ist sehr ineffizient, aber leicht zu verstehen.
object Sum extends App {
def sumCombinations(total: Int, numbers: List[Int]): List[List[Int]] = {
def add(x: (Int, List[List[Int]]), y: (Int, List[List[Int]])): (Int, List[List[Int]]) = {
(x._1 + y._1, x._2 ::: y._2)
}
def sumCombinations(resultAcc: List[List[Int]], sumAcc: List[Int], total: Int, numbers: List[Int]): (Int, List[List[Int]]) = {
if (numbers.isEmpty || total < 0) {
(0, resultAcc)
} else if (total == 0) {
(1, sumAcc :: resultAcc)
} else {
add(sumCombinations(resultAcc, sumAcc, total, numbers.tail), sumCombinations(resultAcc, numbers.head :: sumAcc, total - numbers.head, numbers))
}
}
sumCombinations(Nil, Nil, total, numbers.sortWith(_ > _))._2
}
println(sumCombinations(15, List(1, 2, 5, 10)) mkString "\n")
}
Beim Ausführen wird Folgendes angezeigt:
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)
List(1, 1, 1, 2, 2, 2, 2, 2, 2)
List(1, 2, 2, 2, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5)
List(1, 1, 1, 1, 1, 1, 1, 1, 2, 5)
List(1, 1, 1, 1, 1, 1, 2, 2, 5)
List(1, 1, 1, 1, 2, 2, 2, 5)
List(1, 1, 2, 2, 2, 2, 5)
List(2, 2, 2, 2, 2, 5)
List(1, 1, 1, 1, 1, 5, 5)
List(1, 1, 1, 2, 5, 5)
List(1, 2, 2, 5, 5)
List(5, 5, 5)
List(1, 1, 1, 1, 1, 10)
List(1, 1, 1, 2, 10)
List(1, 2, 2, 10)
List(5, 10)
Das sumCombinations()
Funktion kann für sich allein verwendet werden, und das Ergebnis kann weiter analysiert werden, um die "beste" Lösung (die kürzeste Liste) oder die Anzahl der Lösungen (die Anzahl der Listen) anzuzeigen.
Beachten Sie, dass die Anforderungen auch dann möglicherweise nicht vollständig erfüllt sind. Es kann vorkommen, dass die Reihenfolge jeder Liste in der Lösung von Bedeutung ist. In einem solchen Fall müsste jede Liste so oft dupliziert werden, wie es eine Kombination ihrer Elemente gibt. Oder wir interessieren uns nur für die Kombinationen, die unterschiedlich sind.
Zum Beispiel könnten wir in Betracht ziehen, List(5, 10)
dass dies zwei Kombinationen ergeben sollte: List(5, 10)
und List(10, 5)
. Denn List(5, 5, 5)
je nach Anforderung können drei oder nur eine Kombination angegeben werden. Für ganze Zahlen sind die drei Permutationen äquivalent, aber wenn es sich um Münzen handelt, wie im "Münzwechselproblem", sind sie es nicht.
Ebenfalls nicht in den Anforderungen angegeben ist die Frage, ob jede Zahl (oder Münze) nur einmal oder mehrmals verwendet werden darf. Wir könnten (und sollten!) Das Problem auf eine Liste von Vorkommenslisten jeder Zahl verallgemeinern. Dies führt im wirklichen Leben dazu, dass "mit einem Satz Münzen (und nicht mit einem Satz Münzwerte) ein bestimmter Geldbetrag verdient werden kann". Das ursprüngliche Problem ist nur ein besonderer Fall in diesem Fall, in dem jede Münze so oft vorkommt, wie erforderlich ist, um den Gesamtbetrag mit jedem einzelnen Münzwert zu ermitteln.