トヨタシステムズプログラミングコンテスト2023(AtCoder Beginner Contest 330)の A - Counting Passes を Elixir で解きましたので,ご報告します.
問題
簡易ローカルテスト環境の構築
次のようなMakefileを書きました.
.phony: all clean
test: test_ex
test_ex:
elixir test.exs < in1.txt | diff - out1.txt
elixir test.exs < in2.txt | diff - out2.txt
elixir test.exs < in3.txt | diff - out3.txt
Code.eval_file("main.exs")
Main.main()
入力例1をin1.txt
,出力例1をout1.txt
のように与え,main.exs
に解答を書きます.その後,make
コマンドを実行します.
解答例
defmodule Main do
def main() do
[_n, l] = read_int_list()
a = read_int_list()
a
|> Enum.filter(& &1 >= l)
|> Enum.count()
|> IO.puts()
end
def read_int_list() do
IO.read(:line)
|> String.trim()
|> String.split(" ")
|> Enum.map(&String.to_integer/1)
end
end
関数Main.read_int_list/0
は,IO.read/2
で標準入力から1行読み取り,String.trim/1
で改行文字を取り除いた後,String.split/3
で空白文字で区切ってリストにしてから,Enum.map/2
で各要素について,String.to_integer/1
を適用して文字列を数字に変換し,その結果のリストを返します.
これにより,まず,n
とl
を読み込みます.n
は使用しないので,_n
と書くことで,n
を読み捨てます.
次にリストa
を読み込みます.その後,a
をEnum.filter/2
でl
以上の値を持つ要素を抽出し,Enum.count/1
で個数を数えます.最後に結果をIO.puts/2
で出力します.
別解
a
を使わずに,パイプラインで直接繋ぐこともできます.
defmodule Main do
def main() do
[_n, l] = read_int_list()
read_int_list()
|> Enum.filter(& &1 >= l)
|> Enum.count()
|> IO.puts()
end
def read_int_list() do
IO.read(:line)
|> String.trim()
|> String.split(" ")
|> Enum.map(&String.to_integer/1)
end
end
さらにEnum.count/2
を使って,Enum.filter/2
とEnum.count/1
を合わせてしまいます.
defmodule Main do
def main() do
[_n, l] = read_int_list()
read_int_list()
|> Enum.count(& &1 >= l)
|> IO.puts()
end
def read_int_list() do
IO.read(:line)
|> String.trim()
|> String.split(" ")
|> Enum.map(&String.to_integer/1)
end
end
実行時間やメモリ使用量はともかくとして,Elixirはデータ変換パラダイムによって,書きたいことをストレートに,かつ簡潔に書けますね.