Haskell函数generate实现求助:生成交替取自有序列表的升序列表
Haskell
generate 函数修正:生成所有合法交替升序列表 问题背景
给定两个升序整数列表xs和ys,需实现类型为generate :: [Int] -> [Int] -> [[Int]]的函数,返回所有满足以下条件的升序列表:
- 元素交替取自
xs、ys - 首元素来自
xs - 末元素来自
ys
用户现有代码在部分测试用例中运行正常,但在测试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]] - 实际输出:
[[1,2],[1,6],[1,67],[5,6],[5,67],[8,67],[1,2,5,6,8,67],[5,6,8,67],[8,67]]
现有代码问题分析
现有代码的more函数仅生成从当前起始点开始的最长可能交替序列,未考虑中途停止(比如生成[1,2,5,6]这种未取完所有元素的序列),也未处理每一步选择不同后续元素的情况;processMore仅遍历xs的每个起始位置调用一次more,无法覆盖所有合法的序列组合。
修正后的代码
import Data.List (nub) generate :: [Int] -> [Int] -> [[Int]] generate xs ys = nub $ concatMap (\x -> generateFromX x xs' ys) xs where xs' = drop 1 xs -- 跳过当前x,后续xs的可选元素从下一个开始 -- 从x开始,后续可选xs元素为restXs,可选ys元素为ys,生成所有合法序列 generateFromX :: Int -> [Int] -> [Int] -> [[Int]] generateFromX x restXs ys = -- 生成所有以x开头、接一个符合条件y的二元组 [[x, y] | y <- ys, x < y] ++ -- 生成更长的序列:选一个y>x后,递归生成后续交替序列并添加前缀 concatMap (\y -> map (x:y:) (generateFromY y restXs (dropWhile (<= y) ys))) (filter (> x) ys) -- 从y开始,后续可选xs元素为restXs,可选ys元素为restYs,生成所有合法序列(末元素必须是ys) generateFromY :: Int -> [Int] -> [Int] -> [[Int]] generateFromY y restXs restYs = -- 选一个x>y后,递归生成后续交替序列并添加前缀 concatMap (\x -> map (x:) (generateFromX x (dropWhile (<= x) restXs) restYs)) (filter (> y) restXs)
代码逻辑说明
- 整体入口:遍历
xs中的每个元素作为起始点,调用generateFromX生成所有以该元素开头的合法序列。 - generateFromX:
- 先生成所有以当前
x开头、接一个满足x < y的y的二元组。 - 对每个符合条件的
y,递归调用generateFromY生成更长的交替序列,再将x:y:前缀添加到这些序列前。
- 先生成所有以当前
- generateFromY:
- 遍历所有大于当前
y的x(来自剩余的xs元素),递归调用generateFromX生成后续序列,再将x:前缀添加到这些序列前。 - 由于要求末元素必须来自
ys,二元组的情况已在generateFromX中处理,递归会自然终止于以ys元素结尾的序列。
- 遍历所有大于当前
- 去重处理:用
nub去除可能存在的重复序列。
测试验证:运行generate [1,5,8] [2,6,67],会得到预期的全部12个序列。
内容的提问来源于stack exchange,提问作者Jinxy
相关产品推荐
相关产品推荐

