九九表(Elixir)

# はじめに
- @yuta_vamdemic さんの[go修行1日目 九九表](https://qiita.com/yuta_vamdemic/items/0a20847f51764543ad86)を拝見しまして、私はぜひ[Elixir](https://elixir-lang.org/)でやってみようとおもいました
- [Elixir](https://elixir-lang.org/)は`Elixir 1.10.4 (compiled with Erlang/OTP 23)`を使いました

## ハイライト

```elixir:lib/hello_multiplication.ex
defmodule HelloMultiplication do
  @max 20
  @maximum_number_of_digits Integer.to_string(@max * @max) |> String.length()

  def run do
    for(x <- 1..@max, y <- 1..@max, do: x * y)
    |> Enum.map(&Integer.to_string/1)
    |> Enum.map(&String.pad_leading(&1, @maximum_number_of_digits))
    |> Enum.chunk_every(@max)
    |> Enum.map(&Enum.join(&1, " "))
    |> Enum.each(&IO.puts/1)
  end
end
```

- [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2)
- [Enum.chunk_every/2](https://hexdocs.pm/elixir/Enum.html#chunk_every/2)
- [Enum.join/2](https://hexdocs.pm/elixir/Enum.html#join/2)
- [Enum.each/2](https://hexdocs.pm/elixir/Enum.html#each/2)
- [Integer.to_string/1](https://hexdocs.pm/elixir/Integer.html#to_string/1)
- [String.pad_leading/3](https://hexdocs.pm/elixir/String.html#pad_leading/3)
- [IO.puts/2](https://hexdocs.pm/elixir/IO.html#puts/2)
- [for/1](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#for/1)
- [|>/2](https://hexdocs.pm/elixir/Kernel.html#%7C%3E/2)
- [def/2](https://hexdocs.pm/elixir/Kernel.html#def/2)
- [defmodule/2](https://hexdocs.pm/elixir/Kernel.html#defmodule/2)



# 0. インストールとプロジェクトの作成
- まずは[Elixir](https://elixir-lang.org/)をインストールしましょう
    - 手前味噌ですが、[インストール](https://qiita.com/torifukukaiou/items/d04d0273749c41eb50af#0-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB) などを参考にしてください
- インストールができましたら以下のコマンドでプロジェクトを作ります

```console
$ mix new hello_multiplication
$ cd hello_multiplication
```

# ソースコードを書く 〜その1〜
- 1x1 〜 9x9までの結果をみやすく表示しています

```elixir:lib/hello_multiplication.ex
defmodule HelloMultiplication do
  def run do
    for(x <- 1..9, y <- 1..9, do: x * y)
    |> Enum.map(&Integer.to_string/1)
    |> Enum.map(&String.pad_leading(&1, 2))
    |> Enum.chunk_every(9)
    |> Enum.map(&Enum.join(&1, " "))
    |> Enum.each(&IO.puts/1)
  end
end
```

## 実行

```elixir
$ iex -S mix

iex> HelloMultiplication.run
 1  2  3  4  5  6  7  8  9
 2  4  6  8 10 12 14 16 18
 3  6  9 12 15 18 21 24 27
 4  8 12 16 20 24 28 32 36
 5 10 15 20 25 30 35 40 45
 6 12 18 24 30 36 42 48 54
 7 14 21 28 35 42 49 56 63
 8 16 24 32 40 48 56 64 72
 9 18 27 36 45 54 63 72 81
:ok
```

- うん、動いています :tada::tada::tada:

# ソースコードを書く 〜その2〜
- インドでは20の段まで暗記していると聞きます(99x99まで覚えているという！？　説も）
- 9という数字を`@max`で定義して、何桁分空白をいれたらいいかを計算で求めるようにしています
- [|>](https://hexdocs.pm/elixir/Kernel.html#%7C%3E/2)で全部つなげようと、無名関数を駆使しています

```elixir:lib/hello_multiplication.ex
defmodule HelloMultiplication do
  @max 20

  def run do
    for(x <- 1..@max, y <- 1..@max, do: x * y)
    |> Enum.map(&Integer.to_string/1)
    |> (fn list ->
          {list, list |> Enum.max_by(&String.length/1) |> String.length()}
        end).()
    |> (fn {list, maximum_number_of_digits} ->
          Enum.map(list, &String.pad_leading(&1, maximum_number_of_digits))
        end).()
    |> Enum.chunk_every(@max)
    |> Enum.map(&Enum.join(&1, " "))
    |> Enum.each(&IO.puts/1)
  end
end
```

## 実行

```elixir
iex> recompile

iex> HelloMultiplication.run
  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20
  2   4   6   8  10  12  14  16  18  20  22  24  26  28  30  32  34  36  38  40
  3   6   9  12  15  18  21  24  27  30  33  36  39  42  45  48  51  54  57  60
  4   8  12  16  20  24  28  32  36  40  44  48  52  56  60  64  68  72  76  80
  5  10  15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90  95 100
  6  12  18  24  30  36  42  48  54  60  66  72  78  84  90  96 102 108 114 120
  7  14  21  28  35  42  49  56  63  70  77  84  91  98 105 112 119 126 133 140
  8  16  24  32  40  48  56  64  72  80  88  96 104 112 120 128 136 144 152 160
  9  18  27  36  45  54  63  72  81  90  99 108 117 126 135 144 153 162 171 180
 10  20  30  40  50  60  70  80  90 100 110 120 130 140 150 160 170 180 190 200
 11  22  33  44  55  66  77  88  99 110 121 132 143 154 165 176 187 198 209 220
 12  24  36  48  60  72  84  96 108 120 132 144 156 168 180 192 204 216 228 240
 13  26  39  52  65  78  91 104 117 130 143 156 169 182 195 208 221 234 247 260
 14  28  42  56  70  84  98 112 126 140 154 168 182 196 210 224 238 252 266 280
 15  30  45  60  75  90 105 120 135 150 165 180 195 210 225 240 255 270 285 300
 16  32  48  64  80  96 112 128 144 160 176 192 208 224 240 256 272 288 304 320
 17  34  51  68  85 102 119 136 153 170 187 204 221 238 255 272 289 306 323 340
 18  36  54  72  90 108 126 144 162 180 198 216 234 252 270 288 306 324 342 360
 19  38  57  76  95 114 133 152 171 190 209 228 247 266 285 304 323 342 361 380
 20  40  60  80 100 120 140 160 180 200 220 240 260 280 300 320 340 360 380 400
:ok
```

- うん、たしかに動いています

# ソースコードを書く 〜その3〜
- その2は動いてはいますがわかりにくい部分があります
- よく考えると最大の桁数は`@max * @max`のはずなのであらかじめ定数にしておけばよさそうです
- ということでこちらを結論にしておきます
- その1で書いたソースの`9`や`2`を[Module attributes](https://elixir-lang.org/getting-started/module-attributes.html)にしましたという格好となりました

```elixir:lib/hello_multiplication.ex
defmodule HelloMultiplication do
  @max 20
  @maximum_number_of_digits Integer.to_string(@max * @max) |> String.length()

  def run do
    for(x <- 1..@max, y <- 1..@max, do: x * y)
    |> Enum.map(&Integer.to_string/1)
    |> Enum.map(&String.pad_leading(&1, @maximum_number_of_digits))
    |> Enum.chunk_every(@max)
    |> Enum.map(&Enum.join(&1, " "))
    |> Enum.each(&IO.puts/1)
  end
end
```

# Wrapping Up
- お好きな言語で九九をお楽しみください
- **Enjoy!**