Codeforces 26A - A. Almost Prime

26A - A. Almost Prime

素因数分解したときに、素因数の種類が 2 つかどうか求める問題。

import Data.List

factorize :: Int -> [Int]
factorize 1 = [1]
factorize n = fac 2 n
  where
    fac p n
      | n == 1         = []
      | n `mod` p == 0 = p : fac p (n `div` p)
      | otherwise      = fac (p+1) n

isAlmostPrime :: Int -> Bool
isAlmostPrime n = 2 == (length $ nub $ factorize n)

calc :: Int -> Int
calc n = sum [1 | i <- [1..n], isAlmostPrime i]

main = do s <- getLine
          print $ calc $ read s

リストの中にpredを満たすものがいくつあるか個数を返す関数が標準ライブラリにありそうだと思って調べたけれど見つかりませんでした。

Codeforces 148A - A. Insomnia cure

148A - A. Insomnia cure

calc :: Int -> Int -> Int -> Int -> Int -> Int
calc k l m n d = d - length [i | i <- [1..d],
                             i `mod` k /= 0,
                             i `mod` l /= 0,
                             i `mod` m /= 0,
                             i `mod` n /= 0]

main = do s <- getContents
          let [k, l, m, n, d] = map read $ lines s :: [Int]
          print $ calc k l m n d

英文の読み方

英文が難しいけど、意味が分からないところは読み飛ばして最後まで読んでみる。それからまたはじめに戻って全体を読み返す。それを何度か繰り返すと、なんとなく意味がつかめてくる箇所が出てくる(分からないままのことも多いけど)。それから入力と出力のサンプルも確認する。入出力は問題文の意味を読み解くヒントになることも少なくない。

Codeforces 3A - A. Shortest path of the king

3A - A. Shortest path of the king

import Data.Char      

parse :: String -> (Int, Int)
parse s = (digitToInt (s!!1), ord (s!!0) - ord 'a' + 1)

calc :: (Int, Int) -> (Int, Int) -> [String]
calc (sr, sc) (dr, dc)
  | sr == dr && sc == dc = []
  | otherwise =  dir : calc (r, c) (dr, dc)
    where
      r = sr + signum (dr - sr)
      c = sc + signum (dc - sc)
      dir = (move sc dc "R" "L") ++ (move sr dr "U" "D")
      move src dst lt gt
        | src == dst = ""
        | src <  dst = lt
        | otherwise  = gt

main :: IO ()       
main = do s <- getLine
          t <- getLine
          let moves = calc (parse s) (parse t)
          print $ length moves
          mapM_ putStrLn moves

mapM_ はまだよく意味が分かっていない。

参考:

Codeforces 139A - A. Petr and Book

139A - A. Petr and Book

calc :: Int -> [Int] -> Int
calc n pages = calc' n (cycle pages) (cycle [1..7])
  where
    calc' n (p:pages) (d:dayWeek)
      | n <= p    = d
      | otherwise = calc' (n-p) pages dayWeek

main = do s <- getLine
          t <- getLine
          print $ calc (read s) (map read $ words t)

Codeforces 146A - A. Lucky Ticket

146A - A. Lucky Ticket

import Data.Char

isLucky :: String -> Bool
isLucky s = all (\c -> c == '4' || c == '7') s

calc :: String -> String
calc s = if isLucky s && sum hd == sum tl
         then "YES"
         else "NO"
  where
    xs = map digitToInt s 
    n  = length s `div` 2
    hd = take n xs
    tl = drop n xs

main = do s <- getLine
          t <- getLine
          putStrLn $ calc t

Codeforces 219A - A. k-String

219A - A. k-String

  • 文字列をソートする。
  • 同じ文字でグルーピング。
  • グルーピングした文字列の長さが k の倍数なら、k-string は作れる。そうでなければ k-string は作れない
import Data.List

calc :: Int -> String -> Maybe String
calc k s = if all (\t -> length t `mod` k == 0) xs
           then Just $ (foldl1 (++) . replicate k) $ kString1 xs
           else Nothing
  where
    xs = group $ sort s
    kString1 []     = ""
    kString1 (x:xs) = take (length x `div` k) x ++ kString1 xs

main = do s <- getLine
          t <- getLine
          case calc (read s) t of
            Just x  -> putStrLn x
            Nothing -> print (-1) -- -1 は括弧で囲む必要がある