Elixirでyukicoderのチュートリアル問題をやってみた。

Elixirを少し入門してみました。
コーディング練習がてら[yukicoder](https://yukicoder.me)のチュートリアル問題をいくつかやってみたので公開してみようと思います。
以下の問題は、[初心者のためのガイド](https://yukicoder.me/wiki/guide)の「チュートリアルの問題を解いてみましょう！」です。

※コードの末尾にある`Main.main()`は提出する際には不要です。

# [No.9000 Hello World!（テスト用）](https://yukicoder.me/problems/12)

```elixir:no9000_HelloWorld.exs
defmodule Main do
    def main do
        IO.puts("Hello World!")
    end
end
Main.main()
```

```bash:HelloWorld!
$ elixir no9000_HelloWorld.exs 
Hello World!
```
`IO.puts`で出力するだけです。

# [No.480 合計](https://yukicoder.me/problems/no/480)
```elixir:No.480_合計
defmodule Main do
    def main do
        n = IO.gets("")
              |> String.trim
              |> String.to_integer
        Enum.to_list(1..n)
          |> Enum.reduce(&(&1 + &2))
          |> IO.puts
    end
end
Main.main
```

```bash:No.480_合計
$ elixir no480_sum.exs 
3
6
$ elixir no480_sum.exs 
1
1
$ elixir no480_sum.exs 
10
55
```

`IO.gets("")`で1行取得しています。　※この方法以外に`IO.read`も使えるみたいです。
`|>`はパイプライン演算子で、結果を次の処理の第1引数として渡せます(Linuxの`|`と似た動き)
`IO.gets("")`で取得した値には改行が含まれてしまうため`String.trim`で削除しています。
`String.to_integer`で数字から数値に変換しています。
`Enum.to_list(1..n)`で1からnのリストを生成しています。
`Enum.reduce()`でリストに対して&(&1 + &2)を適用して、リスト内の数値を合計しています。
キャプチャ演算子(&)を使用して匿名関数を省略形で記述しています。
`&(&1 + &2)`と`fn(a, b) -> a + b end`は同じ内容になります。
最後に`IO.puts()`で出力しています。

合計するのに`Enum.reduce()`を使用しましたが、`Enum.sum()`を使用しても数値リストを合計できます。


# [No.9001 標準入出力の練習問題（テスト用）](https://yukicoder.me/problems/527)
```elixir:No.9001_標準入出力の練習問題（テスト用）
defmodule Main do
    def main do
        input1 = IO.gets("")
                    |> String.trim
                    |> String.split(" ")
                    |> Enum.map(&String.to_integer/1)
                    |> Enum.sum()
        input2 = IO.gets("") |> String.trim
        IO.puts("#{input1} #{input2}")
    end
end
Main.main()
```

```bash:No.9001_標準入出力の練習問題（テスト用）
$ elixir no9001_inout.exs 
1 2
yukicoder
3 yukicoder
```

IO.gets()を2回使用して2行取得しています。
1行目、取得後に`String.split(" ")`でスペース区切りにリストにしています。
`Enum.map`を使用して取得したリストの数字を数値に変換しています。
`&String.to_integer/1`はキャプチャ演算子を使用しています。
`&String.to_integer/1`と`&String.to_integer(&1)`は同じです。
`/1`はアリティと言い、引数の数を表しています。
`Enum.sum()`で取得した数値リストを合計しています。
2行目、取得しているだけです。
`IO.puts("#{} #{}")`でスペース区切りで結果を出力しています。

# [No.9002 FizzBuzz（テスト用）](https://yukicoder.me/problems/16)
```elixir:No.9002_FizzBuzz（テスト用）
defmodule Main do
    def main do
        n = IO.gets("")
              |> String.trim
              |> String.to_integer
        Enum.to_list(1..n)
            |> Enum.map(&fizzbuzz/1)
    end
    
    def fizzbuzz(n) when rem(n, 15) === 0, do: IO.puts("FizzBuzz")
    def fizzbuzz(n) when rem(n, 3) === 0, do: IO.puts("Fizz")
    def fizzbuzz(n) when rem(n, 5) === 0, do: IO.puts("Buzz")
    def fizzbuzz(n), do: IO.puts(n)

end
Main.main()

```

```bash:No.9002_FizzBuzz（テスト用）
$ elixir no9002_fizzbuzz.exs 
1
1
$ elixir no9002_fizzbuzz.exs 
16
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
```
取得した値をリスト化して`Enum.map`を使用してリストの各数値に対して作成したfizzbuzz関数を適用しています。
関数はガード(when)を使用して値に応じて処理内容を分岐しています。
`rem(n, 15)`で剰余を求めています。


# [No.9008 空白区切りで与えられる数値データの合計値を求める（テスト用）](https://yukicoder.me/problems/no/9008)
```elixir:No.9008_空白区切りで与えられる数値データの合計値を求める（テスト用）
defmodule Main do
    def main do
        _ = IO.gets("")
                  |> String.trim
                  |> String.to_integer
        IO.gets("")
            |> String.trim
            |> String.split(" ")
            |> Enum.map(&String.to_integer/1)
            |> Enum.sum()
            |> IO.puts()
    end
end
Main.main
```

```bash:No.9008_空白区切りで与えられる数値データの合計値を求める（テスト用）
$ elixir no9008_sum_numbers.exs 
3
39 100 11
150
$ elixir no9008_sum_numbers.exs 
10
0 1 2 3 4 5 6 7 8 9
45
$ elixir no9008_sum_numbers.exs 
5
1000000 1000000 1000000 1000000 1000000
5000000
$ elixir no9008_sum_numbers.exs 
2
77144313318378908 540010193228652352
617154506547031260
```

1行目は不要なので`_`を使用して明示的に使用しないことを表しています。
2行目は取得した値をNo.9001 標準入出力の練習問題（テスト用）と同じ方法で合計して出力しています。


# [No.9009 改行区切りで与えられる数値データの合計値を求める（テスト用）](https://yukicoder.me/problems/no/9009)
```elixir:No.9009_改行区切りで与えられる数値データの合計値を求める（テスト用）
defmodule Main do
  def main do
    n = IO.gets("")
          |> String.trim
          |> String.to_integer
    Enum.reduce(1..n, 0, fn _x, a -> sum(a) end)
        |> IO.puts
  end
  def sum(b) do
    n = IO.gets("")
          |> String.trim
          |> String.to_integer
    b + n
  end
end
Main.main
```

```bash:No.9009_改行区切りで与えられる数値データの合計値を求める（テスト用）
$ elixir no9009_sum_numbers.exs 
3
39
100
11
150
$ elixir no9009_sum_numbers.exs 
10
0
1
2
3
4
5
6
7
8
9
45
$ elixir no9009_sum_numbers.exs 
5
1000000
1000000
1000000
1000000
1000000
5000000
$ elixir no9009_sum_numbers.exs 
2
77144313318378908
540010193228652352
617154506547031260
```

ちょっとトリッキー？なやり方で合計してみました。
1行目で取得した回数`Enum.reduce`を使用して入力を受け取り合計しています。
`Enum.reduce`のaに順次合計していきます。
`sum(a)`では受け取った値に入力された値を合計して、`Enum.reduce`に戻しています。

ちょっと説明が難しい・・。
もっといいやり方があるかもですね。

#[No.46 はじめのn歩](https://yukicoder.me/problems/43)
```elixir:No.46_はじめのn歩
defmodule Main do
  def main do
    [a, b] = IO.gets("")
                |> String.trim
                |> String.split(" ")
                |> Enum.map(&String.to_integer/1)
    
    Float.ceil(b/a)
        |> Kernel.trunc
        |> IO.puts
    
  end
end
Main.main()
```

```bash:No.46_はじめのn歩
$ elixir no46_first_n.exs 
2 5
3
$ elixir no46_first_n.exs 
10 100
10
$ elixir no46_first_n.exs 
123456789 987654321
9
```

スペース区切りの数値をリストとして取得してパターンマッチングでa, bに入れています。
`Float.ceil`で`b/a`の結果を切り上げています。
`Kernel.trunc`で少数を切り捨てています。
最後に出力しています。


#[No.388 階段(1)](https://yukicoder.me/problems/no/388)

```elixir:No.388_階段(1)
defmodule Main do
  def main do
    [s, f] = IO.gets("")
              |> String.trim
              |> String.split(" ")
              |> Enum.map(&String.to_integer/1)
    div(s,f)
        |> Kernel.trunc
        |> add_one
        |> IO.puts
  end
  def add_one(x), do: x + 1
end
Main.main()
```

```elixir:No.388_階段(1)
$ elixir no388_stairs_1.exs 
13 13
2
$ elixir no388_stairs_1.exs 
39 10
4
$ elixir no388_stairs_1.exs 
50 123
1
```

スペース区切りの数値をリストとして取得してパターンマッチングでs, fに入れています。
divで除算し`Kernel.trunc`で少数を切り捨てています。
その後、現在居る段数と一階層分の段数が同数の場合1階上にいることになるため、1足しています。
最後に出力しています。

#おわり
やってみた内容は以上です。
なんとなくElixirの構文はわかってきたので、
次はPhoenixなどフレームワークを学んでみようと思います。

#参考
https://qiita.com/wotsushi/items/b71c7bb5831d18246e9a
https://www.amazon.co.jp/dp/4274219151
https://elixir-lang.org/
https://elixir-lang.jp/
https://elixirschool.com/ja/