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.
Комментариев нет:
Отправить комментарий
Thanks for your posting!