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

  • 1
    いいね
  • 0
    コメント

問題 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 挑戦中