La soluzione di questo problema è stata data un milione di volte su Internet. Il problema si chiama problema di cambio moneta . Puoi trovare soluzioni su http://rosettacode.org/wiki/Count_the_coins e modello matematico su http://jaqm.ro/issues/volume-5,issue-2/pdfs/patterson_harmel.pdf (o cambio monete Google problema ).
A proposito, la soluzione Scala di Tsagadai è interessante. Questo esempio produce 1 o 0. Come effetto collaterale, elenca sulla console tutte le possibili soluzioni. Visualizza la soluzione, ma non riesce a renderla utilizzabile in alcun modo.
Per essere il più utile possibile, il codice dovrebbe restituire List[List[Int]]
a per consentire di ottenere il numero di soluzione (lunghezza dell'elenco di elenchi), la soluzione "migliore" (l'elenco più breve) o tutte le possibili soluzioni.
Ecco un esempio È molto inefficiente, ma è facile da capire.
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")
}
Quando eseguito, visualizza:
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)
La sumCombinations()
funzione può essere utilizzata da sola e il risultato può essere ulteriormente analizzato per visualizzare la soluzione "migliore" (l'elenco più breve) o il numero di soluzioni (il numero di elenchi).
Si noti che anche in questo modo, i requisiti potrebbero non essere pienamente soddisfatti. Potrebbe accadere che l'ordine di ciascun elenco nella soluzione sia significativo. In tal caso, ogni elenco dovrebbe essere duplicato tante volte quante sono le combinazioni dei suoi elementi. Oppure potremmo essere interessati solo alle combinazioni diverse.
Ad esempio, potremmo considerare che List(5, 10)
dovrebbero dare due combinazioni: List(5, 10)
e List(10, 5)
. PerList(5, 5, 5)
potrebbe dare tre combinazioni o una sola, a seconda delle esigenze. Per gli interi, le tre permutazioni sono equivalenti, ma se abbiamo a che fare con le monete, come nel "problema del cambio di monete", non lo sono.
Inoltre, nei requisiti non è indicata la questione se ciascun numero (o moneta) possa essere utilizzato solo una o più volte. Potremmo (e dovremmo!) Generalizzare il problema in un elenco di elenchi di occorrenze di ciascun numero. Ciò si traduce nella vita reale in "quali sono i modi possibili per guadagnare una certa quantità di denaro con un insieme di monete (e non un insieme di valori di moneta)". Il problema originale è solo un caso particolare di questo, in cui abbiamo tutte le occorrenze di ogni moneta necessarie per fare l'importo totale con ogni singolo valore di moneta.