type Grade = (Int, String, Double)
type DB = [Grade]

average :: [Double] -> Double
average l = sum l / fromIntegral (length l)

averageGrade :: DB -> Double
averageGrade = average . map (\(_,_,grade) -> grade)

listStudents :: DB -> [Int]
listStudents = removeDuplicates . map (\(fn,_,_) -> fn)

removeDuplicates :: (Eq a) => [a] -> [a]
removeDuplicates [] = []
removeDuplicates (x:xs) = x : removeDuplicates (filter (/=x) xs)

averageStudentGrade :: DB -> Int -> Double
averageStudentGrade db st = average [ grade | (fn, _, grade) <- db, fn == st]

listFailed :: DB -> String -> [Int]
listFailed db subj = [ fn | (fn, subject, grade) <- db, grade < 3, subject == subj ]

bestStudent :: DB -> Int
bestStudent db = snd (maximum [ (averageStudentGrade db fn, fn) | fn <- listStudents db ])
-- тук използваме следният трик:
-- двойката (grade1,fn1) е по-голяма от двойката (grade2,fn2) точно когато
-- grade1 > grade2 или grade1 == grade2 и fn1 > fn2.
-- Понеже няма значение кой студент ще върнем ако най-добрите успехи съвпадат,
-- връщаме този с по-голям факултетен номер
Последно модифициране: вторник, 17 януари 2012, 00:27