Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local maxima of list using fold

Is there any way to find out local maxima of a list using foldr or foldl or maybe I have to use unfoldr because of first and last elements of list aren't local maximums?

I understand how to find it using recursion with guards, e.g.

localMax :: [Int] -> [Int]
localMax []       = []
localMax (x:[])   = []
localMax (x:y:[]) = []
localMax (x:y:z:zs)
    | y > z && y > x = y:localMax (y:z:zs)
    | otherwise = localMax (y:z:zs)
like image 413
zerospiel Avatar asked Feb 26 '14 15:02

zerospiel


1 Answers

You could, but itd be very ugly. Mostly because to find the local maximum, you'll need to know the previous and next elements.

The previous element is no problem, but a fold isn't supposed to know anything about the elements after it.

As a possible approach

 import Data.List (zip3)

 localMax xs = map proj2
               . filter isLocalMax
               $ zip3 xs (tail xs) (drop 2 xs)
   where isLocalMax (x, y, z) = x < y && z < y
         proj2 (_,x,_) = x

So we shift the list by one and two and zip it all together so [a, b, c, d, e] becomes [(a, b, c), (b, c, d), (c, d, e)] then we just use map and filter to select the appropriate elements.

Do note though that map and filter could be smashed into one foldr if you really wanted to.

like image 192
Daniel Gratzer Avatar answered Sep 27 '22 18:09

Daniel Gratzer