我想制作一个方法,我可以给它一个长度列表,它会返回笛卡尔坐标的所有组合,直到这些长度。用例子更容易解释:
cart [2,5]
Prelude> [ [0,0],[0,1],[0,2],[0,3],[0,4],[1,0],[1,1],[1,2],[1,3],[1,4] ]
cart [2,2,2]
Prelude> [ [0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1] ]
简单的列表理解不起作用,因为我不知道列表将持续多长时间。虽然我喜欢Haskell对于许多问题的简单性,但是我可以在5分钟内编写程序(用C或其他东西),而Haskell给我一个动脉瘤!
这个特定问题的解决方案可以帮助我很多;在处理这样的事情时,我也很想听听你的思考过程。
答案 0 :(得分:13)
嗯..
cart = sequence . map (enumFromTo 0 . subtract 1)
期望[[a]] -> [[a]]
函数执行我们期望的库中已存在的函数是合理的。因此,如果一个人不熟悉sequence
,那么发现它只是hoogling的简单问题。
编辑:正如newacct所指出的那样:
cart = mapM (enumFromTo 0 . subtract 1)
也可以通过将之前的解决方案提供给HLint来找到。
答案 1 :(得分:12)
这可以递归地解决。首先,Cartesian product of nothing是{∅}:
cart [] = [[]]
(或者,如果空产品无效,则仅定义1元素形式:
cart [x] = [[i] | i <- [0 .. x-1]]
)
然后,x:xs
的笛卡尔积可以写为
cart (x:xs) = [i:rest | i <- [0 .. x-1], rest <- cart xs]
一般来说,如果你要编写一个需要列表长度为 N 的函数 f ,那么试着想办法让 f(N) 取决于较小的列表,例如仅 f(N - 1),然后求解基本情况 f(0)或 f(1)等。这将问题转化为一个可以轻松解决的递归。
答案 2 :(得分:7)
我打赌你的程序解决方案会涉及递归。我们的Haskell解决方案也将涉及递归。
所以,递归。首先是递归案例。
cart (c : cs) = [i : r | i <- [0 .. c-1], r <- rcart]
where rcart = cart cs
这里我们只是说,对于每个可能的初始坐标,以及剩余长度的笛卡尔坐标的每个可能组合,我们明确地将坐标与其余坐标结合起来。
然后是基本情况。
cart [] = [[]]
您可能会想cart [] = []
。我起初做了。但想想基本情况下递归案例需要什么。