💻

ElixirでAtCoder Beginners Selection解いてみた

2024/12/23に公開

はじめに

Elixirの入門としてAtCoder Beginners Selectionを解いてみました。

AtCoder Beginners Selectionとは

「AtCoderに登録したけど何をしていいか分からない・・・!」という人に向けて作られた、初心者向け問題集です。

https://atcoder.jp/contests/abs

PracticeA - Welcome to AtCoder

https://atcoder.jp/contests/abs/tasks/practice_1
入出力の練習問題

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

https://atcoder.jp/contests/abs/tasks/abc086_a
偶奇判定用の関数を実装

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

https://atcoder.jp/contests/abs/tasks/abc081_a
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

https://atcoder.jp/contests/abs/tasks/abc081_b
整数の割り算、余りの計算には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

https://atcoder.jp/contests/abs/tasks/abc087_b
全探索する

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

https://atcoder.jp/contests/abs/tasks/abc083_b

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

https://atcoder.jp/contests/abs/tasks/abc088_b
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

https://atcoder.jp/contests/abs/tasks/abc085_b
入力が少し難しい
重複削除した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

https://atcoder.jp/contests/abs/tasks/abc085_c
リスト内包括で条件を満たすケースを列挙

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 - 白昼夢

https://atcoder.jp/contests/abs/tasks/arc065_a
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

https://atcoder.jp/contests/abs/tasks/arc089_a
解けません。。。(TLEがとれない)
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