Harmonic series
Harmonic series
This is the very simple interview question: check that series are harmonic, i.e.
list of numbers are line (kx + b) - two close elements always have the same difference (k).
Naive implementation is:
-- Naive version of checking if sequence of numbers are harmonic (difference -- between neighbords is the const) -- Folding function with args (prev, diff, result) rf (p, d, Nothing) c = (c, d', Just True) where d' = c - p rf (p, d, Just False) c = (c, d, Just False) rf (p, d, Just True) c = (c, d', Just $ d == d') where d' = c - p harm [] = False harm (hd:xs) = let (_, _, Just x) = foldl rf (hd, 0, Nothing) xs in x main = do print $ harm [1, 2, 3, 4, 5, 6, 9] print $ harm [1, 2, 3, 4, 5, 6] print $ harm [2, 4, 6, 8]
where we are folding items and keep on each step tuple (prev, diff, result), where result
is Just True, Just False or Nothing on first item. Actually this code has problem: it
can not process harm [2] or harm [].
Another version may calculate difference between neighboards and then to calculate difference in the same way again:
1 2 3 4 6
-1 -1 -1 -2
0 0 -1!
After it we can summarize all items and if result is 0 then we have harmonic numbers:
neighOp op [] = [] neighOp op l@(hd:xs) = zipWith op l xs harm [] = False harm [x] = False harm ns = 0 == (foldl1 (+) $ neighOp (-) $ (neighOp (-) ns)) main = do print $ harm [1, 2, 3, 4, 5, 6, 9] print $ harm [1, 2, 3, 4, 5, 6] print $ harm [2, 4, 6, 8] print $ harm [2] print $ harm []
3d version does not folding all items but drops all 0's until find first non zero which means that non-harmonic series are found:
neighOp op [] = [] neighOp op l@(hd:xs) = zipWith op l xs harm [] = False harm [x] = False harm ns = case dropWhile (==0) $ neighOp (-) $ neighOp (-) ns of [] -> True _ -> False main = do print $ harm [1, 2, 3, 4, 5, 6, 9] print $ harm [1, 2, 3, 4, 5, 6] print $ harm [2, 4, 6, 8] print $ harm [2] print $ harm []
Case will be lazy so calculations happens until first non-zero item in 2nd difference.