Created
July 26, 2010 17:42
-
-
Save naota/490902 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data Racer = Racer { name :: String | |
, score :: Int | |
, wins :: [Int] | |
} deriving (Show) | |
main :: IO () | |
main = interact func | |
scores :: [Int] | |
scores = [25, 18, 15, 12, 10, 8, 6, 4, 2, 1] | |
func :: String -> String | |
func s = onechamp racerdata ++ "\n" ++ anotherchamp racerdata ++ "\n" | |
where racedata = convert s | |
racerdata = fromRaceData racedata [] | |
(!!!) :: [Int] -> Int -> Int | |
lst !!! n = if (length lst) <= n then 0 else (lst !! n) | |
onechamp :: [Racer] -> String | |
onechamp rd = name . check 0 $ candicates 0 [] rd | |
where candicates _ cs [] = cs | |
candicates hi cs (r:rs) = if score r > hi | |
then candicates (score r) [r] rs | |
else if score r == hi | |
then candicates hi (r:cs) rs | |
else candicates hi cs rs | |
check _ [] = error "" | |
check _ (r:[]) = r | |
check n (r:rs) = let up = filter (\x -> (wins r)!!!n < (wins x)!!!n) rs | |
in if null up | |
then check (n+1) $ r:(filter (\x -> (wins r)!!!n == (wins x)!!!n) rs) | |
else check n up | |
anotherchamp :: [Racer] -> String | |
anotherchamp rd = name $ check 1 $ checkPoint $ candicates 0 [] rd | |
where candicates _ cs [] = cs | |
candicates hi cs (r:rs) = if (wins r)!!!0 > hi | |
then candicates ((wins r)!!!0) [r] rs | |
else if (wins r)!!!0 == hi | |
then candicates hi (r:cs) rs | |
else candicates hi cs rs | |
check _ [] = error "" | |
check _ (r:[]) = r | |
check n (r:rs) = let up = filter (\x -> (wins r)!!!n < (wins x)!!!n) rs | |
in if null up | |
then check (n+1) $ r:(filter (\x -> (wins r)!!!n == (wins x)!!!n) rs) | |
else check n up | |
checkPoint [] = error "" | |
checkPoint (r:[]) = [r] | |
checkPoint (r:rs) = let up = filter (\x -> (score r) < (score x)) rs | |
in if null up | |
then r:(filter (\x -> (score r) == (score x)) rs) | |
else checkPoint up | |
fromRaceData :: [[String]] -> [Racer] -> [Racer] | |
fromRaceData [] racer = racer | |
fromRaceData (r:rs) racer = fromRaceData rs $ f (zip [0..] r) racer | |
where f [] nowr = nowr | |
f ((n, na):rest) nowr = let rc = getOrNew na racer | |
newwin = plusWins n $ wins rc | |
newsc = score rc + scores !!! n | |
in f rest $ update na (rc {score = newsc, wins = newwin}) nowr | |
getOrNew :: String -> [Racer] -> Racer | |
getOrNew na rs = let lst = filter (\r -> name r == na) rs | |
in if null lst | |
then Racer {name=na,score=0,wins=[]} | |
else head lst | |
update :: String -> Racer -> [Racer] -> [Racer] | |
update na new rs = new:filter (\r -> name r /= na) rs | |
convert :: String -> [[String]] | |
convert s = convert' n (tail ls) | |
where ls = lines s | |
n = read $ head ls :: Int | |
convert' 0 _ = [] | |
convert' n' ls' = [take m (tail ls')] ++ convert' (n'-1) (drop m (tail ls')) | |
where m = (read $ head ls')::Int | |
plusWins :: Int -> [Int] -> [Int] | |
plusWins 0 [] = [1] | |
plusWins n [] = 0:plusWins (n-1) [] | |
plusWins 0 (x:xs) = (x+1):xs | |
plusWins n (x:xs) = x:plusWins (n-1) xs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment