module Exercise02 where import Data.List (minimumBy, nub, sort, (\\)) import Data.Ord (comparing) {-H2.1a)-} twoThirdsAverageWinners :: [(String, Int)] -> [String] twoThirdsAverageWinners gs = getClose ave 0 gs where -- get the name with closest bid getClose :: Int -> Int -> [(String, Int)] -> [String] getClose ave diff list | null result = getClose ave (diff + 1) list | otherwise = result where -- filter out the bids outside the range result = [name | (name, bid) <- list, abs (bid - ave) <= diff] ave = getTwoThirdsAverage bids where -- get the average of all bids getTwoThirdsAverage :: [Int] -> Int getTwoThirdsAverage list = sum list * 2 `div` (3 * length list) (_, bids) = unzip gs {-H2.1b)-} lowestUniqueBidder :: [(String, Int)] -> String -- filter out duplicated bids, get the lowerest one lowestUniqueBidder bs | length bs == 1 = head names | null unique = "Nobody" | otherwise = head unique where unique = [name | bid <- sorted, names <- [[fst play | play <- bs, snd play == bid]], length names == 1, name <- names] sorted = sort bids (names, bids) = unzip bs {-H2-} -- returns the shortest list in a list of lists shortest :: [[Int]] -> [Int] shortest = minimumBy (comparing length) -- returns the set of all players in a tournament players :: [[Int]] -> [Int] players tournament = [1 .. length tournament] -- returns the dominion of player i dominion :: [[Int]] -> Int -> [Int] dominion tournament i = tournament !! (i - 1) {-H2.2a)-} dominators :: [[Int]] -> Int -> [Int] dominators tournament i = [dominator | dominator <- players tournament, dominator /= i, notElem dominator $ dominion tournament i] {-H2.2b)-} covers :: [[Int]] -> Int -> Int -> Bool covers tournament i j = null jRest where jRest = jD \\ iD iD = dominion tournament i jD = dominion tournament j {-2.2c)-} dominant :: [[Int]] -> [Int] -> Bool dominant _ [] = False dominant tournament xs = null [notX | x <- xs, notX <- [t | t <- players tournament, t `notElem` xs], notX `notElem` dominion tournament x] {-WETT-} {-H2.2d)-} copeland :: [[Int]] -> [Int] copeland tournament = [player | player <- players tournament, maximum (map length tournament) == length (dominion tournament player)] {-H2.2e)-} uncoveredSet :: [[Int]] -> [Int] uncoveredSet tournament = [player | player <- players tournament, null [otherPlayer | otherPlayer <- players tournament, otherPlayer /= player, covers tournament otherPlayer player]] {-H2.2f)-} -- get the top one, and find a list from the top one topCycle :: [[Int]] -> [Int] topCycle tournament = include $ copeland tournament where include :: [Int] -> [Int] include tops = if null rest then tops else include $ tops ++ nub rest where w top = dominion (map (dominators tournament) $ players tournament) top \\ tops rest = concatMap w tops {-TTEW-}