【doctestつき】AtCoder に登録したら解くべき精選過去問 10 問を"Elixir"で解いてみた


※この記事は[Elixir Advent Calendar 2018](https://qiita.com/advent-calendar/2018/elixir)の9日目です

8日目は yujikawaさんの[【入門】FlutterとElixir/PhoenixのGraphQLでTODOアプリを作る（Elixir編）](https://qiita.com/yujikawa/items/88ffb1c88393ca2dbbf9)です！
こちらも是非！

# Elixirで競プロ解けるかって？・・・できらぁ！！
競技プログラミングの代表的なサービスであるAtCoderには過去問精選問題というものがあり、C++をはじめ様々な言語で解かれています
[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067#5-%E9%81%8E%E5%8E%BB%E5%95%8F%E7%B2%BE%E9%81%B8-10-%E5%95%8F)

筆者も以前Goで解きました
[AtCoder 過去問精選 10 問 をGoでやってみた](https://qiita.com/koyo-miyamura/items/17ddf9aa70fb1479e6eb)

そしてfukuoka.exキャストとして最近ハマって勉強している**`Elixir`**という言語
・・・えっ？知らない？それでは以下を読んでみてください笑
[【fukuoka.ex】学生エンジニアがElixirに興味を持ったきっかけと初心者にオススメの勉強法](https://qiita.com/koyo-miyamura/items/86f1148e4a8a7c591e55)

ザっと調べたところElixirで解かれている問題はなさそう（まぁAtCoder対応してないんですが笑）
ということでやってみよ～

# doctest使ってみる
とはいえAtCoderが対応していないのでテスト結果は自分で考えないといけないです
まぁそれはサンプル入力や他の方のを見ればいいんですが、いちいち打つのはめんどう・・・
しかし！！Elixirには**doctest**というものが標準装備されています！！

百聞は一見に如かずということで以下をどうぞ

```elixir:sample.ex
defmodule Sample do
  @doc """
  ## Examples

      iex> Sample.hello()
      :world

  """
  def hello do
    :world
  end
end
```

```elixir:sample_test.exs
defmodule SampleTest do
  use ExUnit.Case
  doctest Sample
end
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/edd8bc5d-c8e7-dcde-f6c1-ba59a6b0e255.png)

**めっちゃ簡単！！！**

ちなみにiexは、RubyでいうirbやPythonでいうipythonのように、コマンドライン上でElixirを実行するツールで、Elixirに標準装備されています

# mixで準備
Elixirにはmixというパッケージ管理やらディレクトリ生成やらを行ってくれるツールが標準装備されています
rubyでいうgemとか、PHPでいうcomposerみたいなの

標準でdoctestできるようになっているので、これを活用していきましょう

`mix new atcoder_practice`としてディレクトリの生成を行います

```bash
atcoder_practice/
├── README.md
├── _build
│   └── test
│       └── lib
│           └── atcoder_practice
│               ├── consolidated
│               │   ├── Elixir.Collectable.beam
│               │   ├── Elixir.Enumerable.beam
│               │   ├── Elixir.IEx.Info.beam
│               │   ├── Elixir.Inspect.beam
│               │   ├── Elixir.List.Chars.beam
│               │   └── Elixir.String.Chars.beam
│               └── ebin
│                   ├── Elixir.AtcoderPractice.beam
│                   └── atcoder_practice.app
├── config
│   └── config.exs
├── lib
│   └── atcoder_practice.ex
├── mix.exs
└── test
    ├── atcoder_practice_test.exs
    └── test_helper.exs

9 directories, 14 files
```

今回はdoctestしか使わないので`test/atcoder_practice_test.exs`を以下のように書き換えます

```elixir:test/atcoder_practice_test.exs
defmodule AtcoderPracticeTest do
  use ExUnit.Case
  doctest AtcoderPractice

  # test "greets the world" do
  #   assert AtcoderPractice.hello() == :world
  # end
end
```

※elixirで標準入力を受け取るには以下の記事のように`IO.gets`を使うとかすればいいんですが、①テストしにくい、②関数型であるElixir的には副作用のある関数はあまり望ましくない、という点から標準入力はすでに行われているものとし、解答に含めないことにします
気になる方は以下の記事が詳しいです

[yukicoder（競プロ）でElixirの修行をする](https://qiita.com/wotsushi/items/b71c7bb5831d18246e9a)
[【fukuoka.ex】学生エンジニアがElixirに興味を持ったきっかけと初心者にオススメの勉強法](https://qiita.com/koyo-miyamura/items/86f1148e4a8a7c591e55#%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E9%9D%A2%E7%99%BD%E3%81%84%E5%8B%89%E5%BC%B7%E6%B3%95)

簡単なサンプルも以下に貼っておきますね

```elixir:aとbを標準入力から受け取って和を返す
defmodule Solution do
  a = IO.gets("") |> String.trim() |> String.to_integer
  b = IO.gets("") |> String.trim() |> String.to_integer
  IO.puts(a+b)
end
```

# それでは解答しましょ～
## 第 1 問:  [ABC 086 A - Product](https://beta.atcoder.jp/contests/abc086/tasks/abc086_a) (100 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/6ce04cd4-e429-bd67-8a45-706d9350cfff.png)

Elixirで余りを計算するときは%ではなくrem/2を使うみたい
%はハッシュ（連想配列）で使うから区別するためですかね
（remは関数名で/2は引数の数です。Elixirでは同名の関数でも引数の数が異なると機能も異なるように実装可能なのでこのような表記をします）

あとreturn使うとエラーになるので注意

Elixirは条件分岐の方法としてifの他にcase, withなどが存在します
パターンマッチという機能が強力なのでcaseで書くことが多いかも

```elixir
  @doc """
  ## Examples

      iex> AtcoderPractice.product(3,4)
      'Even'

      iex> AtcoderPractice.product(1,21)
      'Odd'

  """
  def product(a, b) do
    case rem(a * b, 2) do
      0 ->
        'Even'

      1 ->
        'Odd'
    end
  end
```

mix test してみよう（　＾ω＾）・・・
ドキドキ・・・
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/e23a7b7c-af3f-d5a0-031e-589c523f597a.png)

よっしゃ！できてる！！

## 第 2 問:  [ABC 081 A - Placing Marbles](https://beta.atcoder.jp/contests/abc081/tasks/abc081_a) (100 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/a23f6eb8-b640-60aa-1f62-46ba7aab769f.png)

問題に準拠したいため入力は文字列としました
`String.codepoints()`を使って1文字ずつのlistにしてEnum系の関数を使えるようにしたあと、`Enum.count`で条件に合う要素の数をカウントしています
関数型でない言語だと`count`というローカル変数を定義してループしていくと思いますが、Elixirなら1行で書けます（すごい！）

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.placing_marbles("101")
      2

      iex> AtcoderPractice.placing_marbles("000")
      0

      iex> AtcoderPractice.placing_marbles("100")
      1

      iex> AtcoderPractice.placing_marbles("111")
      3

      iex> AtcoderPractice.placing_marbles("010")
      1
  """
  def placing_marbles(s) do
    s |> String.codepoints() |> Enum.count(fn x -> x == "1" end)
  end
```

ちなみにドキュメントによるとiex>の行を改行せずに続けると一続きのテストとして実行されます
改行するとそれぞれ別のテストとみなされるようです

![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/607baedb-329f-9cd2-4a9c-d40b0078e6d7.png)

[ExUnit.DocTest – ExUnit v1.7.4](https://hexdocs.pm/ex_unit/ExUnit.DocTest.html)

## 第 3 問:  [ABC 081 B - Shift Only](https://beta.atcoder.jp/contests/abc081/tasks/abc081_b) (200 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/8da5d13b-3927-5b32-e263-a15dbf0ae5ef.png)

再帰使うとこんな感じでしょうか
Elixirにはループのためのforが存在しないので、繰り返し処理は少し頭使いますね
ElixirにはEnumという便利なモジュールがあるので、それを使えばスッキリ書けます！
ちなみに`Enum.all`はリストの全要素が条件を満たすかどうかを判定する関数です

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.shift_only("8 12 40")
      2

      iex> AtcoderPractice.shift_only("5 6 8 10")
      0

      iex> AtcoderPractice.shift_only("382253568 723152896 37802240 379425024 404894720 471526144")
      8

      iex> AtcoderPractice.shift_only("4 4")
      2

      iex> AtcoderPractice.shift_only("2 2")
      1

  """
  def shift_only(s) do
    list = s |> String.split() |> Enum.map(&String.to_integer/1)
    shift_only_count(list, 0)
  end

  defp shift_only_count(list, count) do
    if Enum.all?(list, &(rem(&1, 2) == 0)) do
      shift_only_count(Enum.map(list, &div(&1, 2)), count + 1)
    else
      count
    end
  end
```

ちなみにElixirでは関数は**「関数名」と「引数の数（アリティ）」**で区別されます
つまり同じ関数名でも引数の数が異なれば別の関数として扱われます
https://elixirschool.com/ja/lessons/basics/functions/

上記では再帰用の関数をshift_only_countとして別名に分けていましたが、実は同じ名前でもOKです

```elixir
  def shift_only(s) do
    list = s |> String.split() |> Enum.map(&String.to_integer/1)
    shift_only(list, 0)
  end

  defp shift_only(list, count) do
    if Enum.all?(list, &(rem(&1, 2) == 0)) do
      shift_only(Enum.map(list, &div(&1, 2)), count + 1)
    else
      count
    end
  end
```

再帰を使わない解法やスッキリ書ける方法分かる方いればご教授お願いしたいです笑

## 第 4 問:  [ABC 087 B - Coins](https://beta.atcoder.jp/contests/abc087/tasks/abc087_b) (200 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/f4563c15-838d-c379-142b-f64e966d65a2.png)

関数型でない言語で解く場合は素直に3重ループする問題ですが、Elixirは関数型
つまりforがありません

すべてのパターンを列挙したリストを作成し、条件に一致するものをカウントするという方針でやってみます
実装すると以下のようになります

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.coins(2,2,2,100)
      2

      iex> AtcoderPractice.coins(5,1,0,150)
      0

      iex> AtcoderPractice.coins(30,40,50,6000)
      213
  """
  def coins(n500, n100, n50, total) do
    0..n50
    |> Enum.map(fn i ->
      0..n100
      |> Enum.map(fn j ->
        0..n500
        |> Enum.map(fn k ->
          i * 50 + j * 100 + k * 500
        end)
      end)
    end)
    |> List.flatten()
    |> Enum.count(&(&1 == total))
  end
```

Enum.mapを複数適用した結果はリストが入れ子になってしまうので、`List.flatten/1`により1次元に変換してEnum.countしています
しかしちょっと可読性悪いっすね（　＾ω＾）・・・

もうちょっといい書き方ないかな～と思って調べてみると、以下のようにスッキリ書けることを発見！

```elixir
  def coins(n500, n100, n50, total) do
    for i <- 0..n50,
        j <- 0..n100,
        k <- 0..n500 do
      i * 50 + j * 100 + k * 500
    end
    |> Enum.count(&(&1 == total))
  end
```

ちなみにElixirではforはループではなくてリストのジェネレータです（内包表記）
[Elixirの&quot;for&quot;はリストのジェネレータ - Qiita](https://qiita.com/koyo-miyamura/items/eddd3a35e5b07cd84302)

forはこのように複数のenumerableな要素を指定できるので、これを使ってリストを生成すると簡潔に書けますね
[内包表記 · Elixir School](https://elixirschool.com/ja/lessons/basics/comprehensions/)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/5b9c4f06-ae5b-8abf-5798-b1787ebe11ac.png)


## 第 5 問:  [ABC 083 B - Some Sums](https://beta.atcoder.jp/contests/abc083/tasks/abc083_b) (200 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/8a941bf3-1e9b-2cbc-8ffd-d6f139a19c01.png)

各桁の和を計算する関数`digit_sum`を定義して、それを使って`Enum.filter`するのがポイントです
各桁の和を計算する際は、いったん一文字ずつのリストに変換して総和を取ると簡単に計算できます

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.some_sums(20,2,5)
      84

      iex> AtcoderPractice.some_sums(10,1,2)
      13

      iex> AtcoderPractice.some_sums(100,4,16)
      4554
  """
  def some_sums(n, a, b) do
    1..n
    |> Enum.filter(&(a <= digit_sum(&1) and digit_sum(&1) <= b))
    |> Enum.sum()
  end

  defp digit_sum(n) do
    Integer.to_string(n)
    |> String.codepoints() # 1文字ずつのリストへ
    |> Enum.map(&String.to_integer/1)
    |> Enum.sum()
  end
```


## 第 6 問:  [ABC 088 B - Card Game for Two](https://beta.atcoder.jp/contests/abc088/tasks/abc088_b) (200 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/79a4652f-c5ac-c9f0-d810-b92903a74a38.png)

①`card_list`を降順ソート
②それを使ってAliceとBobが取るカードのリストをそれぞれ生成
③和をとる
という流れで解くとスッキリしますね！

`Enum.take_every(2)`はリストの先頭からスタートして2つ飛ばしで要素を取ったリストを返す関数
`Enum.drop_every(2)`はリストの先頭からスタートして2つ飛ばしで要素をスキップしたリストを返す関数
です

* [take_every/2](https://hexdocs.pm/elixir/Enum.html#take_every/2)
* [drop_every/2](https://hexdocs.pm/elixir/Enum.html#drop_every/2)

公式ドキュメントが充実しているので、何かやりたいことがある場合には調べてみるといいと思います
https://hexdocs.pm/elixir/Enum.html#content

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.card_game_for_two([3,1])
      2

      iex> AtcoderPractice.card_game_for_two([2,7,4])
      5

      iex> AtcoderPractice.card_game_for_two([20,18,2,18])
      18

  """
  def card_game_for_two(card_list) do
    sorted_card_dsc = card_list |> Enum.sort(&(&1 >= &2))
    alice_sum = sorted_card_dsc |> Enum.take_every(2) |> Enum.sum()
    bob_sum = sorted_card_dsc |> Enum.drop_every(2) |> Enum.sum()

    alice_sum - bob_sum
  end
```


## 第 7 問:  [ABC 085 B - Kagami Mochi](https://beta.atcoder.jp/contests/abc085/tasks/abc085_b) (200 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/8fc329e8-f3ba-2a5a-4b21-24af94d4c864.png)

問題文をよく読むと、単純に同じ大きさの餅を排除すればいいだけだと分かります
`Enum.uniq`をして`length`で長さを求めるだけですね！スッキリ！

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.kagami_mochi([10,8,8,6])
      3

      iex> AtcoderPractice.kagami_mochi([15,15,15])
      1

      iex> AtcoderPractice.kagami_mochi([50,30,50,100,50,80,30])
      4


  """
  def kagami_mochi(mochi_list) do
    mochi_list
    |> Enum.uniq()
    |> length
  end
```


## 第 8 問:  [ABC 085 C - Otoshidama](https://beta.atcoder.jp/contests/abc085/tasks/abc085_c) (300 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/be22026c-14e2-a0b4-c0ab-8d6c3d8e70eb.png)

こういう出力が一意でない関数のテストはdoctest向いてないですね・・・
doctestに対応させるため、暗黙の制約として「同じ出力が複数存在する場合は10000円が最も少なくなるものを採用する」ことにします

回答の方針として
①全通りの{10000円枚数,5000円枚数,1000円枚数}のリストを生成
②`Enum.filter`にて合計が条件に合うものだけを抽出
③`Enum.at`にて取り出す。ただし条件に合うものがなくて取り出せない場合のデフォルト値は{-1,-1,-1}とする
という方針です

`Enum.at`は地味に「値が取り出せない場合のデフォルト値」を設定できるので、これを活用するとifを使わずにスッキリ書けます！
https://hexdocs.pm/elixir/Enum.html#at/3
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/1ae766d1-9adc-94b5-7aa0-01aea12e8828.png)


```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.otoshidama(9,45000)
      {0,9,0}

      iex> AtcoderPractice.otoshidama(20,196000)
      {-1,-1,-1}

      iex> AtcoderPractice.otoshidama(1000,1234000)
      {2,54,944}

      iex> AtcoderPractice.otoshidama(2000,20000000)
      {2000,0,0}

  """
  def otoshidama(n, total) do
    for i <- 0..n,
        j <- 0..(n - i) do
      {i, j, n - i - j}
    end
    |> Enum.filter(fn {i, j, k} -> i * 10000 + j * 5000 + k * 1000 == total end)
    |> Enum.at(0, {-1, -1, -1})
  end
```

## 第 9 問:  [ABC 049 C - Daydream](https://beta.atcoder.jp/contests/abc049/tasks/arc065_a) (300 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/25574048-2c4e-eb06-fd49-cc5612c630ce.png)

単純に解くと候補となる文字列を全通り列挙すればいいんじゃないかという気もしますが、これは指数関数的に増えていきます
文字列の長さは100000まで考えられるので、下記のように解くとメモリが速攻で死にます笑
**（実行するとPCフリーズしかねないので注意）**

```elixir:メモリ絶対殺すマン.ex
  @doc """
    ## Examples

      iex> AtcoderPractice.day_dream("erasedream")
      :YES

      iex> AtcoderPractice.day_dream("dreameraser")
      :YES

      iex> AtcoderPractice.day_dream("dreamerer")
      :NO

  """
  def day_dream(s) do
    sub_strings = ["dream", "dreamer", "erase", "eraser"]

    strings = generate_strings([""], sub_strings, div(String.length(s), 5))

    if Enum.any?(strings, &(&1 == s)) do
      :YES
    else
      :NO
    end
  end

  defp generate_strings(strings, sub_strings, count) do
    new_strings = for s <- strings, ss <- sub_strings, do: s <> ss

    if count > 0 do
      generate_strings(strings ++ new_strings, sub_strings, count - 1)
    else
      new_strings
    end
  end
```

ここは発想を変えて「チェックしたい文字列集合のどれかに一致するかどうか」を「文字列の先頭から」チェックするとどうでしょう？
しかし、先頭からチェックする場合にdreamが出てきた場合、これが「dreamerの先頭5文字目まで」なのか「dream」なのかが区別できません
同様にdreamerが出てきた場合、「[dream]と[eraseもしくはeraserの2文字目まで]」なのか「dreamer」なのか区別できません

詳しくは元記事の説明をどうぞ
[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～ 第-9-問--abc-049-c---daydream-300-点](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-9-%E5%95%8F--abc-049-c---daydream-300-%E7%82%B9)

一方で「文字列の後ろからチェック」する場合はこのような問題が発生しません
反転させて調べてもいいのですが、Elixirにはcondがあるので、正規表現で条件書き並べてもスッキリ解けそうです

```elixir:メモリに優しい解答.ex
  @doc """
    ## Examples

      iex> AtcoderPractice.day_dream("erasedream")
      :YES

      iex> AtcoderPractice.day_dream("dreameraser")
      :YES

      iex> AtcoderPractice.day_dream("dreamerasererasedreamereraser")
      :YES

      iex> AtcoderPractice.day_dream("dreamerer")
      :NO

  """
  def day_dream(s) do
    cond do
      Regex.match?(~r/dream$/, s) -> day_dream(String.slice(s, 0..-6))
      Regex.match?(~r/dreamer$/, s) -> day_dream(String.slice(s, 0..-8))
      Regex.match?(~r/erase$/, s) -> day_dream(String.slice(s, 0..-6))
      Regex.match?(~r/eraser$/, s) -> day_dream(String.slice(s, 0..-7))
      s == "" -> :YES
      true -> :NO
    end
  end
```

もっといい解き方ありそう（　＾ω＾）・・・

## 第 10 問:  [ABC 086 C - Traveling](https://beta.atcoder.jp/contests/abc086/tasks/arc089_a) (300 点)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/bd16f96c-b920-22d3-6cc1-eaf9ee03ea3d.png)

これは満たすべき条件は
$dt = t_{i+1} - t_{i}$, $dist = {\rm abs}(x_{i+1} - x_{i}) + {\rm abs}(y_{i+1} - y_{i})$ と定義したとき
①`dt >= dist` であること
②`dt`と`dist`の偶奇が一致すること
となります

元記事の説明にもっと詳しく書いています
[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～ 第-10-問--abc-086-c---traveling-300-点](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-10-%E5%95%8F--abc-086-c---traveling-300-%E7%82%B9)

これをElixirで書くと本当にスッキリ書けます
筆者も結構試行錯誤しましたが、最終的なコードの美しさに感動しました笑

方針はこんな感じ
①`[[t1,x1,y1], [t2,x2,y2], ...]`のリストから`[[dt1, dist1], [dt2, dist2], ...] `のリストを作る
②条件判定する

```elixir
  @doc """
    ## Examples

      iex> AtcoderPractice.traveling([[3,1,2], [6,1,1]])
      :Yes

      iex> AtcoderPractice.traveling([[2,100,100]])
      :No

      iex> AtcoderPractice.traveling([[5,1,1], [100,1,1]])
      :No

      iex> AtcoderPractice.traveling([[100,100,0], [102,0,0]])
      :No

  """
  def traveling(list) do
    # [[dt1, dist1], [dt2, dist2], ...] リストを作る
    Enum.map_reduce(list, [0, 0, 0], fn [t2, x2, y2], [t1, x1, y1] ->
      {[t2 - t1, abs(x2 - x1) + abs(y2 - y1)], [t2, x2, y2]}
    end)
    |> elem(0)
    |> Enum.all?(fn [dt, dist] -> dt >= dist and rem(dist, 2) == rem(dt, 2) end)
    |> case do
      true -> :Yes
      _ -> :No
    end
  end
```

ポイントは[Enum.map_reduce/3](https://hexdocs.pm/elixir/Enum.html#map_reduce/3)になります

今回はリストの各要素に対して計算を行うのではなく「現在の要素と**その前の要素**」を使って（distとdtの）計算を行う必要があります
`map_reduce/3`は第一引数に現在の要素、第二引数に**前の要素**を取ることが出来るので、これを使えば「現在の要素と前の要素」を使って計算を行うことができます

map_reduce/3の返り値は{リスト、最後の要素}のタプルになっているので、タプルから要素を取り出す[elem](https://hexdocs.pm/elixir/Kernel.html#elem/2)を使用して取り出しています

※map_reduce使わずに、前（もしくは後）の要素を参照する方法あったら教えていただけると幸いです笑

# まとめ
以前Goでもやったのですが、Elixirでやってみたところ、「慣れ親しんだforが使えなくて悩む」一方で「最終的なコードは尋常じゃなくスッキリ」しますね
[AtCoder 過去問精選 10 問 をGoでやってみた](https://qiita.com/koyo-miyamura/items/17ddf9aa70fb1479e6eb)

RubyやPythonなどでforを使った命令型のプログラミングをする場合、forやifを起点にした制御構文を前提にアルゴリズムを組み立てます
一方で（関数型の）Elixirでやってみた結果、**（問題を）いかにリストなどのenumerable（反復可能）なデータ構造に落とし込むか**がコツだと感じました

つまり、**データに対して何か処理/加工する**というのがElixirの最も得意とする領域なのかもしれません
今後巨大データを扱う場面も増えてきますし、Elixirなら**耐障害性を高く保ちつつ**、**並列/高速にデータ処理**できます
さらに**Phoenix**というRailsライクなフレームワークを使えばWebアプリもサクッと実装出来ますね

まだまだElixir慣れないので、もっといいやり方あるよ！って方いればコメント欄などで教えていただけると幸いですｂ

次回は[Yoosuke](https://qiita.com/Yoosuke)さんの記事です！