2014-03-13 41 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