HaskellでAtCoderやるぜ

1 min read読了の目安(約1500字

A-2倍チェック

蟻本も初級編を読んだので、早速AtCoderをやってみる。
取り敢えず過去問のA-2倍チェック簡単な問題だ。
標準入力を受け取りすべてが数値だったら2倍して標準出力に出す。
数値じゃなければ、errorを出力すればよい。
ただそれだけだ。うっかり、rubyで書きそうになったけど、Haskellで書く。

Haskellの1ファイル実行

Haskellは、stackで環境を作ってstackからbuildして実行していた。
はて、Haskellのファイルをスクリプトを実行するにはどうすればよいのじゃ?
そこからだった。
以下のmain.tsを用意して

main = do
  putStrLn "Hello Haskell"
stack runghc main.hs

で実行する。

Haskellで標準入力と標準出力

getLine と print を使えばよい。

Haskellで文字列を数字変換

readMaybe を使えばよいらしい。
じゃ、こんな感じで書いたぜ。

import Text.Read (readMaybe)

readInt :: String -> Maybe Int
readInt = readMaybe

main :: IO ()
main = do
  a <- readInt <$> getLine
  case a of
      Nothing -> print "error"
      Just a' -> print (a' * 2)

問題に入力例がある。

  • 678 -> 1356 これはOK
  • abc -> error これもOK
  • 0x8 -> 16 何!? 0x8は16進数表記じゃないのか! 16返したからNG errorを返す必要がある。

ということで、悩んだ。
結局、軽くカンニングして以下のコードを書いた。

rInt :: String -> Int
rInt str = read str :: Int

isContainChar :: String -> Bool
isContainChar s = not $ all (\c -> c `elem` ['0'..'9']) s

s2i :: String -> Maybe Int
s2i s
  | isContainChar s = Nothing
  | otherwise = Just $ rInt s

main :: IO ()
main = do
  a <- s2i <$> getLine
  case a of
      Nothing -> print "error"
      Just a' -> print (a' * 2)

25問中12問しか正解できなかった。。
もうダメだーー。

ちなみにこんな感じで書けばよいらしい。

import Data.Char
main = do
    s <- getLine
    case filter (not <$> isDigit) s of
        [] -> print $ 2 * read s
        otherwise -> putStrLn "error"

isDigitを知らなかった&探せなかったのが敗因。
修行が足りぬ。