-- $Id: moments.ghc,v 1.1 2001/02/14 22:12:21 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Brian Gregor
module Main where
import IO
import System
import Numeric
-- read the file
main = do input <- getContents
putAns (lines input)
-- print out the answers
putAns :: [String] -> IO ()
putAns st_nums = do
putStrLn ("n: " ++ (showInt (truncate n) ""))
putStrLn ("median: " ++ (showFFloat (Just 6) (median nums n) ""))
putStrLn ("mean: " ++ (showFFloat (Just 6) mean ""))
putStrLn ("average_deviation: " ++ (showFFloat (Just 6) avg_dev ""))
putStrLn ("standard_deviation: " ++ (showFFloat (Just 6) std_dev ""))
putStrLn ("variance: " ++ (showFFloat (Just 6) var ""))
putStrLn ("skew: " ++ (showFFloat (Just 6) skew ""))
putStrLn ("kurtosis: " ++ (showFFloat (Just 6) kurt ""))
where
n = fromIntegral (length nums)
nums = strToDoub st_nums
mean = (sum nums) / n
deviation = [x-mean | x <- nums]
avg_dev = (sum [abs x | x <- deviation])/ n
var = (sum [x**2 | x <- deviation]) / (n-1)
std_dev = sqrt var
skew = (sum [x**3 | x <- deviation]) / (n*var*std_dev)
kurt = (sum [x**4 | x <- deviation]) / (n*var*var)-3.0
-- convert the strings to doubles
strToDoub :: [String] -> [Double]
strToDoub nums = map conv nums
where conv x = fst (head (readFloat x))
-- calculate the median
median :: [Double] -> Double -> Double
median nums n = mid (mSort nums)
where
mid x
| odd (length x) = x!! midpt
| otherwise = ((x!!(midpt-1)) + (x!!midpt)) / 2.0
midpt :: Int
midpt = floor (n/2)
-- Sorting: the various languages use various algorithms
-- here's an optimized mergesort from
-- "Algorithms - a Functional Approach" by
-- Fethi Rabhe & Guy Lapalme
split :: (Ord a) => [a] -> [[a]]
split [] = []
split (x:xs) = [x]:split xs
merge :: (Ord a) => [a] -> [a] -> [a]
merge [] b = b
merge a [] = a
merge a@(x:xs) b@(y:ys)
| (x<=y) = x : (merge xs b)
| otherwise = y : (merge a ys)
mergepairs :: (Ord a) => [[a]] -> [[a]]
mergepairs [] = []
mergepairs x@[l] = x
mergepairs (l1:l2:rest) = (merge l1 l2) : (mergepairs $! rest)
-- The actual sort
mSort :: (Ord a) => [a] -> [a]
mSort l = ms (split l)
where ms [r] = r
ms l = ms (mergepairs l)