Livebook で AtCoder 始めてみた

## はじめに

先人に倣い、 Elixir で AtCoder を始めてみました

（競技プログラミング初体験）

## 参考にさせて頂いた先人の皆様

@torifukukaiou　さん

https://qiita.com/torifukukaiou/items/9a2235d2476857f9ff32

@koyo-miyamura さん

https://qiita.com/koyo-miyamura/items/9f224a3e56ea75939dca

@GeekMasahiro さん

https://qiita.com/GeekMasahiro/items/20fb0313ef163d7ddc5d

## Elixir バージョン

2023年6月現在、 AtCoder の Elixir は 1.10.2 です

1.12 以降で使える `then` がないのは悲しいです

## 方針

速度も重要ですが、「色々な回答ができること」を目的にしていこうと思います

なので、一つの問題に対して基本的に複数の回答を提出します

## 回答形式

@torifukukaiou　さんが Zenn に書いている記事が分かりやすかったです

https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

また、 Livebook で実装するにあたって、 @GeekMasahiro さんの記事が非常に参考になりました

https://qiita.com/GeekMasahiro/items/20fb0313ef163d7ddc5d

以下の形式で回答を作成します

```elixir
defmodule Main do
  def main do
    :stdio
    |> IO.read(:all)
    |> solve()
    |> IO.puts()
  end

  def solve(input) do
    ...
  end
end
```

AtCoder では `Main.main()` が実行されます

`IO.read(:stdio, :all)` で標準入力を全部読み込み、 `solve()` で変換し、 `IO.puts()` で標準出力に渡します

入力部分はもっと効率化できるようですが、とりあえずこれで進んでみます（理解しやすいため）

複数回答を提出したいので、 1 ノートブックに 1 回答とします

1 ノートブックに 2 回答以上作ろうとしても、 Main モジュールの重複が許されません

## テスト

@koyo-miyamura さん　がやったように doctest も良いかと思ったのですが、、、

```elixir
defmodule Main do
  def main do
    :stdio
    |> IO.read(:all)
    |> solve()
    |> IO.puts()
  end

  defp split_lines(lines) do
    lines
    |> String.trim()
    |> String.split("\n")
  end

  @doc """
  ## Tests

  iex> ~S(
  ...>1
  ...>2
  ...> )
  ...> |> Main.solve()
  3

  """
  def solve(input) do
    input
    |> split_lines()
    |> Enum.map(&String.to_integer/1)
    |> Enum.sum()
  end
end
```

複数行の入力を書きにくいのと、せっかく Livebook なので、セルで実行することにします

```elixir
"""
1
2
"""
|> Main.solve()
|> then(& &1 == 3)
```

結果が `true` になれば OK です

## テンプレート

以下のようなテンプレートを作りました

```elixir
defmodule Main do
  def main do
    :stdio
    |> IO.read(:all)
    |> solve()
    |> IO.puts()
  end

  defp split_lines(lines) do
    lines
    |> String.trim()
    |> String.split("\n")
  end

  defp split_words(words) do
    String.split(words, " ")
  end

  def solve(input) do
    input
    |> split_lines()
    |> hd()
    |> split_words()
    |> Enum.reverse()
    |> hd()
    |> case do
      "1" -> "OUTPUT 1"
      "2" -> "OUTPUT 2"
      _ -> "OUTPUT OTHERS"
    end
  end
end
```

```elixir
"""
INPUT 1
"""
|> Main.solve()
|> then(&(&1 == "OUTPUT 1"))
```

```elixir
"""
INPUT 2
"""
|> Main.solve()
|> then(&(&1 == "OUTPUT 2"))
```

```elixir
"""
INPUT OTHERS
"""
|> Main.solve()
|> then(&(&1 == "OUTPUT OTHERS"))
```

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/atcoder/submit_template.livemd

## 問題・回答例

以下、 AtCoder の問題に対する私の回答を記事にしてリンクを貼っていきます

### Beginners Selection

https://qiita.com/RyoWakabayashi/items/1bdd820f9886bb2f3ea5

https://qiita.com/RyoWakabayashi/items/989769dd71657a923037

https://qiita.com/RyoWakabayashi/items/ad2eaa6aabca8cce896b

https://qiita.com/RyoWakabayashi/items/bfa0dc20c78b0d2513c6

https://qiita.com/RyoWakabayashi/items/69d8c5318bf2cef8b74e

https://qiita.com/RyoWakabayashi/items/14b96c4afbc4d30e57c6

https://qiita.com/RyoWakabayashi/items/977d6ad8508acf51e37d

https://qiita.com/RyoWakabayashi/items/9eb31bcb6f0c63742485

https://qiita.com/RyoWakabayashi/items/c6c51217f334b35b0064

https://qiita.com/RyoWakabayashi/items/fe12267d48a8e950d844

https://qiita.com/RyoWakabayashi/items/916d6eb06743f645da37