1
0
Fork 0

implemented the statistics exercise

main
Oliver Stolle 2026-06-09 21:07:48 +00:00
parent 5dff437064
commit 9b5014ce01
1 changed files with 53 additions and 7 deletions

View File

@ -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