Haskell で AtCoder をやってみる(ABC001)

  • 0
    Like
  • 0
    Comment

    問題 A に挑戦

    import Control.Applicative
    
    main :: IO ()
    main = do
        x <- read <$> getLine
        y <- read <$> getLine
        putStrLn $ show $ x - y
    

    正解!ヒャッハーーーー!!

    問題 B に挑戦

    import Control.Applicative
    import Text.Printf
    
    main :: IO ()
    main = do
        m <- (/1000) . read <$> getLine
        putStrLn $ calc m
    
    calc :: Double -> String
    calc x | x < 0.1               = "00"
           | x >= 0.1 && x <= 5.0   = printf "%02d" $ (truncate $ x * 10 :: Int)
           | x >= 6.0 && x <= 30.0  = show $ (truncate $ x + 50 :: Int)
           | x >= 35.0 && x <= 70.0 = show $ (truncate $ ((x - 30) / 5) + 80 :: Int)
           | otherwise             = "89"
    

    またまた正解!フォーーーーーーー!!!

    問題 C に挑戦

    import Control.Applicative
    
    main :: IO ()
    main = do
        [x, y] <- map read . words <$> getLine
        let calcY = (roundUp $ ((fromIntegral y) / 60) * 10) * 6
        let resY = checkW calcY $ wList wPower wMinSpeed wMaxSpeed
        let resX = if resY == 0 then "C" else checkD (x * 10) $ dList dName dMinAngle dMaxAngle
        putStrLn $ resX ++ " " ++ show resY
    
    roundUp :: (RealFrac a, Integral b) => a -> b
    roundUp x
        | n <= -0.5 = m - 1
        | n >= 0.5  = m + 1
        | otherwise = m
        where (m, n) = properFraction x
    
    class Check a where
        check :: a -> Int -> Bool
    data Direction = Direction { name :: String , minAngle :: Int , maxAngle :: Int } deriving Show
    instance Check Direction where
        check (Direction _ minA maxA) x = if x >= minA && x < maxA then True else False
    
    -- 方位
    dName :: [String]
    dName = ["NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"]
    
    dMinAngle :: [Int]
    dMinAngle = [1125, 3375..32625]
    
    dMaxAngle :: [Int]
    dMaxAngle = [3375, 5625..34875]
    
    dList :: [String] -> [Int] -> [Int] -> [Direction]
    dList [] [] [] = []
    dList (x:xs) (y:ys) (z:zs) = createD x y z : dList xs ys zs
        where
            createD dx dy dz = Direction { name = dx, minAngle = dy, maxAngle = dz }
    
    checkD :: Int -> [Direction] -> String
    checkD t ys = case res of
            [] -> "N"
            otherwise -> name $ head res
        where
            res = flip filter ys $ \y -> check y t
    
    -- 風力
    data Wind = Wind { power :: Int , minSpeed :: Int , maxSpeed :: Int } deriving Show
    instance Check Wind where
        check (Wind _ minS maxS) x = if x >= minS && x < maxS then True else False
    
    wPower :: [Int]
    wPower = [0..11]
    
    wMinSpeed :: [Int]
    wMinSpeed = 0:xs
        where
            xs = map (\x -> (truncate (x * 60)) + 1) [0.2, 1.5, 3.3, 5.4, 7.9, 10.7, 13.8, 17.1, 20.7, 24.4, 28.4]
    
    wMaxSpeed :: [Int]
    wMaxSpeed = map (\x -> (truncate (x * 60)) + 1) [0.2, 1.5, 3.3, 5.4, 7.9, 10.7, 13.8, 17.1, 20.7, 24.4, 28.4, 32.6]
    
    wList :: [Int] -> [Int] -> [Int] -> [Wind]
    wList [] [] [] = []
    wList (x:xs) (y:ys) (z:zs) = createW x y z : wList xs ys zs
        where
            createW wx wy wz = Wind { power = wx, minSpeed = wy, maxSpeed = wz }
    
    checkW :: Int -> [Wind] -> Int
    checkW t ys = case res of
            [] -> 12
            otherwise -> power $ head res
        where
            res = flip filter ys $ \y -> check y t
    

    正解、やったぜ!
    しかし、コードが長すぎるような・・・
    今度書き換えよう・・・

    問題 D 挑戦中