forked from steger/pr3-sose2026
implemented the statistics exercise
parent
5dff437064
commit
9b5014ce01
|
|
@ -1,17 +1,63 @@
|
|||
import Data.List (nub, sortOn)
|
||||
import Data.Function (on)
|
||||
import Data.List (groupBy, nub, sortOn)
|
||||
import System.IO
|
||||
|
||||
-- separator -> Input -> Separated Input
|
||||
-- split :: Char -> String -> [String]
|
||||
split :: Char -> String -> [String]
|
||||
split _ "" = []
|
||||
split sep str =
|
||||
let (word, rest) = break (== sep) str
|
||||
in word : case rest of
|
||||
[] -> []
|
||||
(_ : xs) -> split sep xs
|
||||
|
||||
-- data Entry =
|
||||
-- Data structure for a student entry
|
||||
data Entry = Entry
|
||||
{ firstName :: String,
|
||||
lastName :: String,
|
||||
subject :: String,
|
||||
scores :: [Int]
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
-- averages :: [Entry] -> [(String, Float)]
|
||||
-- Parse CSV content into entries
|
||||
parse :: String -> [Entry]
|
||||
parse content =
|
||||
let lns = lines content
|
||||
(header : rows) = lns
|
||||
in map parseRow rows
|
||||
where
|
||||
parseRow line =
|
||||
let fields = split ',' line
|
||||
[fn, ln, subj] = take 3 fields
|
||||
pts = map read (drop 3 fields) :: [Int]
|
||||
in Entry fn ln subj pts
|
||||
|
||||
-- content -> Entries
|
||||
-- parse :: String -> [Entry]
|
||||
-- Calculate averages per subject
|
||||
averages :: [Entry] -> [(String, Float)]
|
||||
averages entries =
|
||||
let grouped = groupBy ((==) `on` subject) (sortOn subject entries)
|
||||
avgPerSubject grp =
|
||||
let subj = subject (head grp)
|
||||
allScores = concat [scores e | e <- grp]
|
||||
avg = fromIntegral (sum allScores) / fromIntegral (length allScores)
|
||||
in (subj, avg)
|
||||
in map avgPerSubject grouped
|
||||
|
||||
-- Find the best student (most accumulated points)
|
||||
bestStudent :: [Entry] -> (String, Int)
|
||||
bestStudent entries =
|
||||
let best = maximum [(sum (scores e), firstName e ++ " " ++ lastName e) | e <- entries]
|
||||
in (snd best, fst best)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn "Enter a filename: "
|
||||
putStrLn "..."
|
||||
filename <- getLine
|
||||
content <- readFile filename
|
||||
let entries = parse content
|
||||
(name, points) = bestStudent entries
|
||||
avgs = averages entries
|
||||
putStrLn $ "Best student: " ++ name ++ " (" ++ show points ++ " points)"
|
||||
putStrLn "Average points per subject:"
|
||||
mapM_ (\(subj, avg) -> putStrLn $ " " ++ subj ++ ": " ++ show avg) avgs
|
||||
|
|
|
|||
Loading…
Reference in New Issue