我對Haskell很新穎,並且有興趣改進我對問題解決方案的方法「給定一定數量的金錢(以美分爲單位),根據給定的面額列表確定所有更改方法」。這個解決方案確定拆分變更的方式
change :: Int -> [Int] -> [[Int]]
change amt [] = [[]]
change amt [d] = [replicate (quot amt d) d]
change amt (d:denoms) =
if d <= amt then
reverse [0..(quot amt d)] >>= \x ->
[(replicate x d) ++ c | c <- (change (amt - (x*d)) denoms)]
else
change amt denoms
changeUS amt = change amt [25, 10, 5, 1]
-- *Main> changeUS 29
-- [[25,1,1,1,1],[10,10,5,1,1,1,1],[10,10,1,1,1,1,1,1,1,1,1],[10,5,5,5,1,1,1,1],[10,5,5,1,1,1,1,1,1,1,1,1],[10,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[10,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[5,5,5,5,5,1,1,1,1],[5,5,5,5,1,1,1,1,1,1,1,1,1],[5,5,5,1,1,1,1,1,1,1,1,1,11,1,1,1],[5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]
的一個問題是它假定最低DENOM將是1。否則,change amt [d]
情況下是不正確的。在這種情況下,我可以添加if/then
以確保amt
可以被d
整除,但它開始變得有點冗長,我認爲這種情況甚至不是更好的解決方案所必需的。
以某種效率爲代價,您可以刪除單個面額的特例,並且有兩個基本情況:'change 0 _ = [[]]'和'change _ [] = []'。如果你想要它有效率,你需要保留最後一個面額的特例,但是如果它大於1,你可能還會花費很多昂貴的死枝。避免這種情況將需要一些數學來確定您可以從剩下的面額中完全產生什麼樣的總和。對於少量,這將比死衚衕更昂貴。 –