2014-03-13 67 views
1

你好學習哈斯克爾我想出了在鍛鍊的網絡,它要求創建一個列表中給出以下描述的方式整數:有趣的益智

例如,如果整數是3,那麼應該生成一個列表它包含以下內容:

[[3],[1,2],[2,1],[1,1,1]] 

3=3 
1+2=3 
2+1=3 
1+1+1=3 

如果整數是2,那麼這將是:

[[2],[1,1]] 

我想不出一個實現這個的方法,那麼你能否給我提供任何提示?我相信,我必須使用列表理解,但我想不出什麼比這再

+2

看起來好像你必須創建總和的所有排列組合,直到給定值(不包括<= 0)。實現它是棘手的,但不是非常困難。 – Haney

+0

@DavidHaney現在你進一步困惑了我。要創建一個排列,我必須知道一個具體的列表,並採取所有的排列組合。這裏我沒有具體的清單,因爲我不知道我必須生產多少清單。我的意思是在生成3,4列表的情況下產生2,2列表的情況。並且沒有模式。 – JmRag

回答

10

始終與類型簽名開始:

sums :: Int -> [[Int]] 

現在,讓我們想想遞歸。

  1. 什麼是基本情況?你能想到一個答案微不足道的數字嗎?
  2. 比方說,你已經實現了你的功能,它適用於10歲以下的所有數字,所以sums 9例如返回正確的答案。你將如何實施sums 10

,直到你已經回答了這些問題,不要與實現細節(如列表理解與filtermap)理會自己。另一個提示:Haskell程序員喜歡炫耀並創建小點自由函數,但不要讓它讓你困惑。讓事情發揮作用是重要的。最好是有一個工作,但有點「醜陋」的解決方案,而不是盯着屏幕尋找一個優雅的。

祝你好運!

+3

難道你不是指'Int - > [[Int]]'? – MartinHaTh

+0

感謝您的更正,@ bheklilr和@MartinHaTh! – Benesh

2

看起來有點像分區列表。谷歌搜索有一點變成了這個

http://www.haskell.org/pipermail/beginners/2011-April/006832.html

partitions [] = [[]] 
partitions (x:xs) = [[x]:p | p <- partitions xs] 
       ++ [(x:ys):yss | (ys:yss) <- partitions xs] 

產生這樣的

*Main> partitions "abc" 
[["a","b","c"],["a","bc"],["ab","c"],["abc"]] 

現在你需要做的就是內部列表的長度

map (map length) (partitions "abc") 
[[1,1,1],[1,2],[2,1],[3]] 

你也可以改變分區直接給你結果

partitions' 0 = [[]] 
partitions' n = [1:p | p <- partitions' (n-1)] 
      ++ [(1+ys):yss | (ys:yss) <- partitions' (n-1)] 
+0

嗨。你的解決方案很好,但OP明確要求提示,所以在這種情況下,完整的解決方案可能不是一個好的答案。 – Benesh

+1

一個更好的單線,IMO:'總和0 = [[]];總和x = [y:sum | y < - [1..x],sum < - 和$ x - y]' – amalloy