LoginSignup
15
3

More than 1 year has passed since last update.

Livebook で九九の表を作る(Enum版、Nx版)

Last updated at Posted at 2022-11-18

はじめに

我が子が九九を暗唱しているので、私は九九を実装することにします

せっかくなので、 Enum でループするバージョンと Nx で行列演算するバージョンを2種類実装してみましょう

最終的に Kino.DataTable でいい感じに表示してみます

実装の全量はこちら

準備


Mix.install([
  {:nx, "~> 0.4"},
  {:kino, "~> 0.7"}
])

Enum

qq =
  1..9
  |> Enum.to_list()
  |> then(fn list ->
    Enum.map(list, fn x ->
      Enum.map(list, fn y ->
        x * y
      end)
    end)
  end)
  |> dbg()

スクリーンショット 2022-11-18 23.57.13.png

特に解説するまでもないですが、 Enum.to_list(1..9) で 1 から 9 までの配列ができます

その配列を二重ループさせれば九九の出来上がりです

Nx

Nx でやった方がシンプルだよね、と思ったけど結構ゴチャゴチャしてしまった

qq =
  {1, 9}
  |> Nx.iota()
  |> Nx.add(1)
  |> then(&Nx.dot(Nx.transpose(&1), &1))
  |> Nx.to_flat_list()
  |> Enum.chunk_every(9)
  |> dbg()

まず Nx.iota({1, 9}) で 1 * 9 の2次元行列を作ります

スクリーンショット 2022-11-19 0.01.18.png

これだと 0 から 8 になっているので Nx.add で全要素に 1 を足します

スクリーンショット 2022-11-19 0.03.07.png

&Nx.dot(Nx.transpose(&1), &1) つまり、転置行列との内積によって一気に九九の計算をします

スクリーンショット 2022-11-19 0.04.32.png

Nx.to_flat_list() で1次元配列にします

スクリーンショット 2022-11-19 0.06.51.png

Enum.chunk_every(9) で 9 個毎に配列を分割すれば九九の出来上がりです

スクリーンショット 2022-11-19 0.08.13.png

キレイに表示する

DataTable に表示しましょう

qq
|> Enum.map(&%{List.first(&1) => &1})
|> then(&[%{0 => Enum.at(&1, 0)[1]} | &1])
|> Enum.reduce(fn x, merged -> Map.merge(merged, x) end)
|> Kino.DataTable.new()
|> dbg()

Enum.map(&%{List.first(&1) => &1}) で、各段のマップにします

スクリーンショット 2022-11-19 0.11.32.png

then(&[%{0 => Enum.at(&1, 0)[1]} | &1]) で、左端に何の段なのかを示す列を追加します

スクリーンショット 2022-11-19 0.11.56.png

Enum.reduce(fn x, merged -> Map.merge(merged, x) end) により、マップの配列だったのを一つのマップに統合します

スクリーンショット 2022-11-19 0.13.19.png

これを Kino.DataTable.new() に入れればキレイに表示できました

スクリーンショット 2022-11-19 0.10.00.png

まとめ

ループ処理をできるだけ行列演算に変換するための訓練ですね

15
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
3