[英]How can I find the longest increasing section of numbers at list in 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
二進制謂詞切割序列; 切割發生在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
看來你的方式很好 - 而且你似乎已經了解了很多 - 所以我不會為你破壞結果。
起初我認為你應該改變你的功能的類型簽名
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頁面可以解決你的問題。
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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.