💻
ElixirでAtCoder Beginners Selection解いてみた
はじめに
Elixirの入門としてAtCoder Beginners Selectionを解いてみました。
AtCoder Beginners Selectionとは
「AtCoderに登録したけど何をしていいか分からない・・・!」という人に向けて作られた、初心者向け問題集です。
PracticeA - Welcome to AtCoder
入出力の練習問題
ACコード
defmodule Main do
def main do
a = input() |> String.to_integer()
[b,c] = input() |> String.split(" ") |> Enum.map(&String.to_integer/1)
s = input()
IO.puts("#{a+b+c} #{s}")
end
defp input() do
IO.read(:line) |> String.trim()
end
end
ABC086A - Product
偶奇判定用の関数を実装
ACコード
defmodule Main do
def main do
[a, b] = input() |> String.split(" ") |> Enum.map(&String.to_integer/1)
IO.puts(check_number(a*b))
end
defp check_number(n) do
case rem(n, 2) do
0 -> "Even"
1 -> "Odd"
end
end
defp input() do
IO.read(:line) |> String.trim()
end
end
ABC081A - Placing Marbles
String.graphemes()でcharのリストに変換して1の数をカウント
ACコード
defmodule Main do
def main do
input()
|> String.graphemes()
|> Enum.count(fn x -> x == "1" end)
|> IO.puts()
end
defp input() do
IO.read(:line) |> String.trim()
end
end
ABC081B - Shift only
整数の割り算、余りの計算にはdiv()とrem()を使う
ACコード
defmodule Main do
def main do
_n = input() |> String.to_integer()
vec_a = input() |> String.split(" ") |> Enum.map(&String.to_integer/1)
IO.puts solve(vec_a, 0)
end
defp input() do
IO.read(:line) |> String.trim()
end
defp solve(vec, count) do
if Enum.all?(vec, fn x -> rem(x, 2) == 0 end) do
solve(vec |> Enum.map(fn x -> div(x, 2) end), count+1)
else
count
end
end
end
ABC087B - Coins
全探索する
ACコード
defmodule Main do
def main do
a = input() |> String.to_integer()
b = input() |> String.to_integer()
c = input() |> String.to_integer()
x = input() |> String.to_integer()
IO.puts solve(a, b, c, x)
end
defp input() do
IO.read(:line) |> String.trim()
end
defp solve(a, b, c, x) do
for i <- 0..a, j <- 0..b, k <- 0..c do
total = 500 * i + 100 * j + 50 * k
if total == x do
1
else
0
end
end
|> Enum.sum()
end
end
ABC083B - Some Sums
sum = i |> Integer.to_string() |> String.to_charlist() |> Enum.map(fn c -> c-?0 end) |> Enum.sum()
で桁和を計算してA以上B以下ならばiを加算する
ACコード
defmodule Main do
def main do
[n, a, b] = input() |> String.split(" ") |> Enum.map(&String.to_integer/1)
IO.puts solve(n, a, b)
end
defp input() do
IO.read(:line) |> String.trim()
end
defp solve(n, a, b) do
for i <- 1..n do
sum = i |> Integer.to_string() |> String.to_charlist() |> Enum.map(fn c -> c-?0 end) |> Enum.sum()
if a <= sum && sum <= b do
i
else
0
end
end
|> Enum.sum()
end
end
ABC088B - Card Game for Two
Aを降順にソートして奇数番目の要素の和-偶数番目の要素の和を計算
ACコード
defmodule Main do
def main do
_n = input() |> String.to_integer()
vec_a = input() |> String.split(" ") |> Enum.map(&String.to_integer/1)
IO.puts solve(vec_a)
end
defp input() do
IO.read(:line) |> String.trim()
end
defp solve(vec) do
sorted_vec = Enum.sort(vec, :desc)
{odd_sum, even_sum} =
sorted_vec
|> Enum.with_index()
|> Enum.reduce({0, 0}, fn {val, index}, {odd, even} ->
if rem(index, 2) == 0 do
{odd + val, even}
else
{odd, even + val}
end
end)
odd_sum - even_sum
end
end
ABC085B - Kagami Mochi
重複削除したAの長さを出力する
ACコード
defmodule Main do
def main do
inputs = IO.read(:eof) |> String.trim() |> String.split("\n")
[n | vec_a] = inputs
_n = String.to_integer(n)
vec_a = Enum.map(vec_a, &String.to_integer/1)
IO.puts solve(vec_a)
end
defp solve(vec) do
length(Enum.uniq(vec))
end
end
ABC085C - Otoshidama
リスト内包括で条件を満たすケースを列挙
ACコード
defmodule Main do
def main do
[n, y] = input() |> String.split(" ") |> Enum.map(&String.to_integer()/1)
IO.puts solve(n, y)
end
defp input() do
IO.read(:line) |> String.trim()
end
defp solve(n, y) do
result =
(for i <- 0..n, j when i+j <= n and n-i-j>=0 and 10000*i+5000*j+1000*(n-i-j)==y <- 0..n-i, do: {i, j})
|> Enum.at(0)
if result |> is_nil do
"-1 -1 -1"
else
{i, j} = result
"#{i} #{j} #{n-i-j}"
end
end
end
ABC049C - 白昼夢
Sから"eraser" -> "erase" -> "dreamer" -> "dream"の順で愚直に削除して、空文字になるか判定
ACコード
defmodule Main do
def main do
input()
|> solve()
|> then(fn
:yes -> "YES"
:no -> "NO"
end)
|> IO.puts()
end
defp input() do
IO.read(:line) |> String.trim()
end
defp solve(s) do
t = ["eraser", "erase", "dreamer", "dream"]
Enum.reduce(t, s, fn w, acc ->
String.replace(acc, w, "")
end)
|> then(fn
"" -> :yes
new_s when s == new_s -> :no
new_s -> solve(new_s)
end)
end
end
ABC086C - Traveling
TLEコード
defmodule Main do
def main do
inputs = IO.read(:eof) |> String.trim() |> String.split("\n")
_n = hd(inputs)
vec = tl(inputs)
IO.puts solve(0, 0, 0, 0, vec)
end
defp solve(t, x, y, i, vec) do
if length(vec) == 0 do
"Yes"
else
[next_t, next_x, next_y] = hd(vec) |> String.split(" ") |> Enum.map(&String.to_integer()/1)
rem_t = next_t-t
dist = abs(x-next_x)+abs(y-next_y)
if dist <= rem_t and rem(dist,2) == rem(rem_t,2) do
solve(next_t, next_x, next_y, i+1, tl(vec))
else
"No"
end
end
end
end
最後に
Elixirの基本的な構文を学べました。
全体的に実行時間が長い(軽い処理でも平均1s以上かかる)ので、普段使いは別言語の方が良さそう。
Discussion