Haskell Peaks
import Data.Array (Array, listArray, (!))
peaks :: [Int] -> Int
peaks a
| n <= 2 = 0
| totalPeaks == 0 = 0
| otherwise = result
where
n = length a
arr = listArray (0, n - 1) a :: Array Int Int
isPeakAt i = i > 0 && i + 1 < n && arr ! i > arr ! (i - 1) && arr ! i > arr ! (i + 1)
-- running count of peaks seen in a[0 .. i], for i in [0 .. n-2]
sumList = scanl (\acc i -> acc + (if isPeakAt i then 1 else 0)) 0 [1 .. n - 2]
sumArr = listArray (0, n - 2) sumList :: Array Int Int
totalPeaks = sumArr ! (n - 2)
-- sum[n-1] mirrors sum[n-2] in the original algorithm
sumAt idx
| idx == n - 1 = totalPeaks
| otherwise = sumArr ! idx
peakPositions = [i | i <- [1 .. n - 2], isPeakAt i]
lastPeak = last peakPositions
dist = max (gapMax (-1) peakPositions) (n - lastPeak)
where
gapMax _ [] = 0
gapMax prev (p : ps) = max (p - prev) (gapMax p ps)
-- can every block of size i (n/i blocks) contain at least one peak?
checkGroups i = walk 0 i
where
walk lastSum j
| j > n = True
| sumAt (j - 1) <= lastSum = False
| otherwise = walk (sumAt (j - 1)) (j + i)
candidates = [i | i <- [(dist `div` 2) + 1 .. dist - 1], n `mod` i == 0, checkGroups i]
result = case candidates of
(i : _) -> n `div` i
[] -> n `div` head [l | l <- [dist ..], n `mod` l == 0]
This finds the peak positions, then tests how many equal blocks can each contain at least one peak.