HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

UPenn Homework 3: localMaxima :: [Integer] -> [Integer]

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
homeworklocalmaximaupenninteger

Problem

Please see this question for the general description.
Exercise 2: localMaxima :: [Integer] -> [Integer]

A local maximum
of a list is an element of the list which is strictly
greater than both the elements immediately before and after it

localMaxima :: [Integer] -> [Integer]
localMaxima l =
  let getMaxOf3 x y z | x  z = Just y
                          | otherwise = Nothing
      accumulate l2 acc = case l2 of
                           u:v:w:xs -> case (getMaxOf3 u v w) of
                                        Just q -> accumulate (v:w:xs) (q:acc)
                                        Nothing -> accumulate (v:w:xs) acc
                           otherwise -> []
  in reverse (accumulate l [])

Solution

The implementation can be much simpler. The main insight I can offer is to use map and filter instead of Maybe and writing your own accumulate. In addition,

  • Instead of writing case l2 of …, use pattern matching.



  • Look for library functions that you can take advantage of. (Here, I've used tails from Data.List.)



  • In keeping with the "wholemeal programming" goal, use higher-order functions instead of recursion.



  • Higher-order functions also let you use point-free style, which lowers your mini-golf score.



I suggest using where instead of let … in … because the former encourages top-down strategic thinking. You want to write a "one-liner", and add supporting details only if necessary.

import Data.List (tails)

localMaxima :: [Integer] -> [Integer]
localMaxima = map (!!1) . filter isLocalMax . tails
  where
    isLocalMax (a:b:c:_) = a  c
    isLocalMax _         = False


In addition to being shorter, this implementation is more maintainable. You can tell at a glance what map (!!1) . filter isLocalMax . tails does, but reverse (accumulate l []) is mysterious. Furthermore, because isLocalMax is not intertwined with accumulate, you can trace the execution by inspecting tails xs, then (filter isLocalMax . tails) xs, etc.

Code Snippets

import Data.List (tails)

localMaxima :: [Integer] -> [Integer]
localMaxima = map (!!1) . filter isLocalMax . tails
  where
    isLocalMax (a:b:c:_) = a < b && b > c
    isLocalMax _         = False

Context

StackExchange Code Review Q#85104, answer score: 3

Revisions (0)

No revisions yet.