如何在Haskell中找到列表中最长的数字增长部分?

时间:2017-03-03 20:05:10

标签: haskell

例如,列表[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

2 个答案:

答案 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 _    _                              = []

takedrop),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的问题,即groupBygroupBy (<=)

但是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)