如果有人能帮我完成这项任务,我将不胜感激。
令两个整数列表xs和ys按升序排列。定义一个函数
generate :: [Int] -> [Int] -> [[Int]]
按升序返回所有可能的数字列表,其中第一个元素来自xs,第二个元素来自ys,依此类推。每个列表的最后一个元素必须是ys列表中的数字。
示例:
generate [10, 15, 25] [1, 5, 20, 30] == [[10, 20], [10, 30], [15, 20], [15, 30], [25, 30], [10, 20, 25, 30], [15, 20, 25, 30]]
这是我目前所做的,但并不适用于所有情况。
generate :: [Int] -> [Int] -> [[Int]]
generate [] [] = [[]]
generate xs ys = nub $ twos xs ys ++ processMore xs ys
where
twos xs ys = [[x, y] | x <- xs, y <- ys, x < y]
more [] _ = []
more _ [] = []
more (x : xs) (y : ys)
| x < y = x : y : more (filter (> y) xs) ys
| otherwise = more (x : xs) ys
processMore [] _ = []
processMore xs ys = more xs ys : processMore (tail xs) ys
对于上面的例子,它工作正常,但对于这个:
-- this is what i SHOULD get
generate [1, 5, 8] [2, 6, 67] == [[1, 2], [1, 6], [1, 67], [5, 6], [5, 67], [8, 67], [1, 2, 5, 6, 8, 67], [5, 6, 8, 67], [1, 2, 5, 67], [1, 6, 8, 67], [1, 2, 8, 67], [1, 2, 5, 6]]
-- But this is what i actually get( and the problem comes from the processMore, but don't know how to fix it):
generate [1, 5, 8] [2, 6, 67] -> [[1,2],[1,6],[1,67],[5,6],[5,67],[8,67],[1,2,5,6,8,67],[5,6,8,67],[8,67]] -- this is what i get
2条答案
按热度按时间ghhaqwfi1#
我还没有发现你代码中的bug,但我认为有一个更好的方法。你可以把问题看作是有对的构建块(在你的代码中是
twos
函数)。然后,用这些块构建更大的列表,直到你不能再做为止。例如,
使用这个透视图我们可以编写代码,
dgtucam12#
这里有一个我喜欢的方法。与其预先扫描两个列表来寻找有效的对,我更喜欢将其视为遍历列表,在每一点选择“我应该包含这个元素,还是跳过它?”因为我们可以跳过它或包含它,所以我使用
(<|>)
(Alternative中的选择操作符)来指示选择。对于列表,这等效于(++)
。但我认为它更好地将算法描述为选择。如果
xs
为空,我们不能生成任何对;如果它不为空,我们可以跳过第一个x
,或者使用它。要使用它,请丢弃所有小于它的ys
,然后选择一个。选择一个
y
也同样简单,如果ys
为空,我们就不能选择一个,所以我们什么也不产生;否则,我们知道ys
中的所有元素都大于我们选择的x
,所以我们可以自由选择任何y
,跳过第一个y
很容易:把它扔了继续走。选择第一个
y
是这个解决方案中唯一复杂的一行。我们选择了x
和y
,所以我们知道每个解决方案都必须从[x, y]
开始。因此,我们将该列表附加到所有递归解决方案中。递归解决方案是什么?好吧,我们可以到此为止([]
),或者我们可以继续,在丢弃小于我们选择使用的y
的xs
之后,再次调用generate xs ys
。