例如,列表[1,3,4,3,6,7,3]
会提供结果[1,3,4]
或[3,6,7]
。我只能找到后续但不是一节。
通过Naive实现,我找到了子序列
increasing :: Ord a => [a] -> [a]
increasing = maximumBy (comparing length) . map nub
. filter isSorted
. subsequences
答案 0 :(得分:2)
序列的二元谓词切割;剪切发生在(x1, x2)
未成立的第一对x1 <> x2
:
biCut :: (a -> a -> Bool) -> [a] -> ([a], [a])
biCut (<>) (x1 : xs@(x2 : _)) | x1 <> x2 = let (tk, dp) = biCut (<>) xs
in (x1 : tk, dp)
| otherwise = ([x1], xs)
biCut _ xs = (xs, [])
(类似于splitAt
)或
biFst :: (a -> a -> Bool) -> [a] -> [a]
biFst (<>) (x1 : xs@(x2 : _)) | x1 <> x2 = x1 : biFst (<>) xs
| otherwise = [x1]
biFst _ xs = xs
biSnd :: (a -> a -> Bool) -> [a] -> [a]
biSnd (<>) (x1 : xs@(x2 : _)) | x1 <> x2 = biSnd (<>) xs
| otherwise = xs
biSnd _ _ = []
(take
和drop
),forall (<>) xs.
biFst (<>) xs ++ biSnd (<>) xs = xs
biCut (<>) xs = (biFst (<>) xs, biSnd (<>) xs) [CUT]
然后
sections :: (a -> a -> Bool) -> [a] -> [[a]]
sections _ [] = []
sections (<>) xs = let (tk, dp) = biCut (<>) xs
in tk : sections (<>) dp
这样
concat . sections (<>) = id
“Sections”是非空子序列,二进制谓词<>
在后继者之间保持不变。将标准maximumBy
重新制定为总函数:
maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> Maybe a
maximumBy cmp xs | null xs = Nothing
| otherwise = Just (foldl1 max' xs)
where
max' x y = case x `cmp` y of
LT -> y -- Leftmost-biased
_ -> x
然后
longestAsc :: Ord a => [a] -> Maybe [a]
longestAsc = maximumBy (compare `on` length) . sections (<)
是功能。
longestAsc [2,3,2,1,2,3] = Just [1,2,3]
longestAsc [2,1] = Just [2]
longestAsc [] = Nothing
答案 1 :(得分:1)
看起来你的方式很好 - 你似乎已经知道了很多 - 所以我不会为你破坏结果。
首先我认为你应该改变你的功能的类型签名
increasingSequences :: Ord a => [a] -> [[a]]
已经有一个功能可以解决Data.List
的问题,即groupBy
,groupBy (<=)
。
但是groupBy
无法按预期工作,它会与每个组的第一个元素进行比较 - 这对于groupBy (==)
是可以的 - 但不适用于您的情况。
> ghci
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/epsilonhalbe/.ghc/ghci.conf
Prelude> import Data.List
Prelude Data.List> groupBy (<=) [10,9..6]
[[10],[9],[8],[7],[6]]
Prelude Data.List> groupBy (<=) (1:[10,9..6])
[[1,10,9,8,7,6]]
所以你需要自己实现一个 - 最简单的版本恕我直言将使用模式匹配和递归 - 我强烈建议写它并在这里作为答案发布(我将在接下来的几天检查如果你这样做就投票给那个!)
如果真的想要一个剧透,那么实际上有wiki page可以解决您的问题。
groupBy :: (a -> a -> Bool) -> [a] -> [[a]] groupBy rel [] = [] groupBy rel (x:xs) = (x:ys) : groupBy rel zs where (ys,zs) = groupByAux x xs groupByAux x0 (x:xs) | rel x0 x = (x:ys, zs) where (ys,zs) = groupByAux x xs groupByAux y xs = ([], xs)