VSCodeでHaskellプログラムを書こう①:標準入力から値を受け取る
前回の記事
タイトルは初心者向けっぽく、実際に内容は初心者向けなのですが、とにかく手順がややこしいです。
拡張機能としてHaskell関連の一通りの拡張機能とCode-Runnerが入っていることが前提となります。
まず、VSCode上で"Ctrl + ,"を押して、code-runnerを検索します。その中から、Run In Terminalの項目にチェックを入れます。code-runnerでプログラムを実行すると、デフォルトで出力タブに実行されるのですが、出力タブからは標準入力で値を渡すことができないため、ターミナルで実行されるように変更しなければいけません。
とりあえず、ここまでくると実際にプログラムを書く段階に入れます。まずは、"Sample.hs"みたいな適当な名前の新規ファイルを作ります。
今回は標準入力のテストがしたいので、ひとまずAtCoderのPracticeAを解くことを目標としましょう。
プログラムがちゃんとターミナルで実行されるかを確認するために、標準入力から3行受け取って、それをそのまま表示するプログラムを書いてみましょう。
main :: IO()
main = do
a <- getLine
bc <- getLine
s <- getLine
print $ a ++ " " ++ bc ++ " " ++ s
これを実行してターミナル上で、
10
20 30
hello
と入力すれば、
10 20 30 hello
という出力が得られるはずです。
さて、getLineでは入力された値をString型で受け取るので、10 20 30といった数字ももちろんString型です。なので、String型からInt型に変換しなければ計算ができませんね。
"10 20 30"のような文字列を空白で切り分けるwords関数を使えば、["10" "20" "30"]のように文字列のリストを作ることができます。これに対してmap関数で(read::String -> Int)というread関数による要素ごとの型変換をかければ、[10, 20, 30]のような数値のリストが得られます。
main :: IO()
main = do
a <- getLine
bc <- getLine
s <- getLine
print $ a ++ " " ++ bc ++ " " ++ s
let list_abc = words (a ++ " " ++ bc)
let int_abc = map (read::String -> Int) list_abc
print $ int_abc
先ほどの標準入力を受け取るコードに3行追加したものです。この処理を1行にまとめて、
let abc = map (read::String -> Int) . words $ (a ++ " " ++ bc)
のように書くことももちろん可能です。これは半角スペースで区切られた文字列のリストに対して、String型->Int型の変換を行う関数なので、別のプログラムにも流用することができます。具体的には、
stoi = map (read :: String -> Int) . words
のように定義しておいて、
let abc = stoi (a ++ " " ++ bc)
のように使うことができます。
さて、問題の解答は、a, b, c の3つの数値の合計と、適当な文字列 s を半角スペースで区切って1行で表示することでしたので、そのようにプログラムを書き足していきます。具体的には、Int型のリストabcに対して、リスト内の合計を算出するsum関数を使います。全体のコードは次のようになります。
main :: IO()
main = do
a <- getLine
bc <- getLine
s <- getLine
let abc = stoi (a ++ " " ++ bc)
putStrLn $ show (sum abc) ++ " " ++ s
stoi = map (read :: String -> Int) . words
ちなみにstoi関数を定義する位置は、main関数の前でも後でも構いません。これで問題を解くコードが出来上がりました。
この記事が気に入ったらサポートをしてみませんか?