我需要在haskell中创建一个函数,它接收一个数字并返回一个列表列表,其中列表包含所有数字的组合,其总和是接收到的数字。
很难解释所以这是一个例子:
sum1 4 = [ [4], [3,1], [2,2], [1,3], [1,1,2], [1,2,1] , [2,1,1] ]
sum1 3 = [ [3], [2,1], [1,2], [1,1,1]
我需要使用递归和理解列表来执行此操作
修改
这是我的代码:
sum1 n = sum3 (sum2 1 (n-1) n)
sum2 x y n = if ((x+y)==n && x>0 && y>0) then [x,y]:sum2 (x+1) (y-1) n else []
sum3 [] = []
sum3 (x:xs) = sum4 x 1 : sum3 xs
sum4 [] t = []
sum4 (x:xs) t = if not (x == t) then (sum1 x) else x
是的,这是一次考试,但我不知道该怎么做
答案 0 :(得分:3)
我假设这是家庭作业(而且是一个更难的IMO),所以我现在不会破坏一切。
如果您考虑一下,您应该会发现基本上有两种操作可以说明如何从汇总到xs
的列表n
到汇总到n+1
的列表:
1
1
添加到x
xs
因此,如果您设法实施这两项操作,您的任务将变得更加轻松。
第一个并不难(提示 (1:)
是一个额外的1
添加到某个列表的函数 - 现在你必须映射此...)
第二个有点难,虽然几乎相同的分治理念会帮助你。
以下是我将如何开始:
add1Somewhere :: Num a => [a] -> [[a]]
add1Somewhere [i] = [[i+1]]
add1Somewhere (i:is) = ???
(是的,这是部分功能)
1
或在x
中选择任何xs
- 使用第一个x
xs
并在第一位之前就足够了 [1,1]
,那么你可以稍后以两种方式结束[2,2]
:[1,1] -> [2,1] -> [2,2]
和[1,1] -> [1,2] -> [2,2]
- 可以使用Data.List.nub
删除这些内容,或者如果您更改算法以生成有序/过滤结果(不生成[1,1] -> [1,2]
)[1,1,1,1]
我真的无法判断这项运动是否暗示了这样的订单concatMap
(或concat
)因为它已经有一段时间了,你说这是一个旧的考试问题,我认为可以破坏它(如果你不想要的话,不要读它到)
所以这是一个可能的解决方案(不考虑任何性能问题):
import Data.List (nub)
sum1 :: (Eq a, Num a) => a -> [[a]]
sum1 1 = [[1]]
sum1 n = nub $ concatMap add1Somewhere ns ++ map (1:) ns
where ns = sum1 (n-1)
add1Somewhere :: Num a => [a] -> [[a]]
add1Somewhere [i] = [[i+1]]
add1Somewhere (i:is) = ((i+1):is) : map (i:) (add1Somewhere is)
请注意,这会使用concatMap
和nub
,这两者可能也可能不适合。
我希望你能得到基本的想法
oops - 我只是注意到你可以摆脱所有有问题的函数,例如concat
和nub
,因为它足以只是在1
前加{ {1}}或递增第一个列表元素 - 递归将提供所有需要的permations(我提到的不同路径恰好是排列) - 虽然 的顺序不同/ p>
sum1 :: (Eq a, Num a) => a -> [[a]]
sum1 1 = [[1]]
sum1 n = map add1 ns ++ map prep1 ns
where ns = sum1 (n-1)
prep1 is = 1:is
add1 (i:is) = (i+1):is
当然,如果你想要
,你可以用列表理解来替换map
感应n
(假设只有正数)
n=1
注意[1]
是唯一可能的列表
现在假设我们找到了n>0
的所有permations并查看了一些列表xs
总计为n+1
(显然列表必须非空)
现在x
的第一个元素xs = x:ys
将是1
或>1
x=1
- 在这种情况下,prep1
将提供xs
,因为我们的算法通过归纳找到了ys
(请注意sum ys = sum xs - 1 = n
)x>1
- 在这种情况下,我们的算法通过归纳找到(x-1):ys
,add1
将创建xs
(再次因为sum ((x-1):ys) = sum xs - 1 = n
)