Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlinと探索アルゴリズムでスマートに 木構造データをさばく / Handle Tree Data with Kotlin and BFS

YuitoSato
September 22, 2021

Kotlinと探索アルゴリズムでスマートに 木構造データをさばく / Handle Tree Data with Kotlin and BFS

https://server-sider-kotlin.connpass.com/event/224077/

こちらのイベントの資料です。
Kotlinと探索アルゴリズムをつかって木構造のデータをKotlinのコレクションクラスのようにスマートに扱う実装について紹介しています。

YuitoSato

September 22, 2021
Tweet

More Decks by YuitoSato

Other Decks in Technology

Transcript

  1. @ 2021 Loglass Inc. 1
    木構造のデータって意外と多くない?
    Kotlinと探索アルゴリズムでスマートに
    木構造データをさばく
    2021/9/22 株式会社ログラス 佐藤有斗

    View Slide

  2. @ 2021 Loglass Inc. 2
    ● 佐藤 有斗(ゆいと)
    ● 株式会社ログラス
    ● TypeScriptとKotlinとScalaの民
    ● 好きなゲーム: スマブラ、原神
    # 自己紹介

    View Slide

  3. @ 2021 Loglass Inc. 3
    # 株式会社ログラスについて
    ● 創業2年目のシードスタートアップ
    ● プランニング・クラウド
    ● Kotlin × Spring Boot
    次世代型プランニング・クラウド「Loglass」を開発するログラス、 ICCサミット
    「カタパルト・グランプリ」で優勝
    https://prtimes.jp/main/html/rd/p/000000036.000052025.html

    View Slide

  4. @ 2021 Loglass Inc. 4
    木構造のデータってよく使いますか?

    View Slide

  5. @ 2021 Loglass Inc. 5
    # 木構造のデータってこんなの(以下ツリーと呼びます)
    1
    11 13
    12
    111 112
    1121

    View Slide

  6. @ 2021 Loglass Inc. 6
    # 世の中にツリーはとても多い
    ディレクトリ
    部署
    家系図
    法人
    タスク

    View Slide

  7. @ 2021 Loglass Inc. 7
    # Loglassにもたくさん出てくるツリー

    View Slide

  8. @ 2021 Loglass Inc. 8
    # よくあるケース: ツリーを他のツリーに変換したい
    1
    11 13
    12
    111 112
    1121
    10
    110 130
    120
    1110 1120
    11210
    10倍!

    View Slide

  9. @ 2021 Loglass Inc. 9
    再帰関数を書くか、、、

    View Slide

  10. @ 2021 Loglass Inc. 10
    再帰関数を書くか、、、

    View Slide

  11. @ 2021 Loglass Inc. 11
    再帰関数を書くか、、、

    View Slide

  12. @ 2021 Loglass Inc. 12
    読みづらい😇

    View Slide

  13. @ 2021 Loglass Inc. 13
    # 普段使いにはつらい再帰関数
    ● そもそも処理が追いづらい
    ○ 土日の趣味プログラミング以外で出会いたくない

    View Slide

  14. @ 2021 Loglass Inc. 14
    mapみたいな関数があればな〜〜〜〜〜〜〜

    View Slide

  15. @ 2021 Loglass Inc. 15
    例えば: listOf(1,2,3).map { it * 10 }

    View Slide

  16. @ 2021 Loglass Inc. 16
    tree.map { it * 10 } な感じで書きたいな〜

    View Slide

  17. @ 2021 Loglass Inc. 17
    よし、作ろう

    View Slide

  18. @ 2021 Loglass Inc. 18
    1. 木構造を抽象化する
    2. mapのインターフェースを考える
    3. mapの実装をする
    # Tree.mapを作るまでのステップ

    View Slide

  19. @ 2021 Loglass Inc. 19
    1. 木構造を抽象化する
    2. mapのインターフェースを考える
    3. mapの実装をする
    # Tree.mapを作るまでのステップ

    View Slide

  20. @ 2021 Loglass Inc. 20
    # 1. 木構造を抽象化する
    ● ジェネリクスを使って木構造の中のデータは何でもとれるようにする

    View Slide

  21. @ 2021 Loglass Inc. 21
    # 1. 木構造を抽象化する
    ● これでどんなデータでも木構造にできる!

    い え

    Tree
    True
    False False
    Tree
    Hoge1
    Hoge2 Hoge3
    Tree

    View Slide

  22. @ 2021 Loglass Inc. 22
    1. 木構造を抽象化する
    2. mapのインターフェースを考える
    3. mapの実装をする
    # Tree.mapを作るまでのステップ

    View Slide

  23. @ 2021 Loglass Inc. 23
    # 2. mapのインターフェースを考える
    tree.map { it * 10 } な感じで書きたいな〜

    View Slide

  24. @ 2021 Loglass Inc. 24
    # 2. mapのインターフェースを考える
    tree.map { data -> data * 10 }
    ちょっと整形

    View Slide

  25. @ 2021 Loglass Inc. 25
    # 2. mapのインターフェースを考える
    tree.map { data -> data * 10 }
    ここは (Int) -> Int

    View Slide

  26. @ 2021 Loglass Inc. 26
    # 2. mapのインターフェースを考える
    tree.map { data -> data * 10 }
    つまり (Treeの中身) -> 変換したい型の関数

    View Slide

  27. @ 2021 Loglass Inc. 27
    # 2. mapのインターフェースを考える
    tree.map { data -> data * 10 }
    つまり (T) -> S の関数

    View Slide

  28. @ 2021 Loglass Inc. 28
    # 2. mapのインターフェースを考える
    1
    2 4
    3
    Tree

    い え

    Tree
    f: (T) => S
    ● つまりこう

    View Slide

  29. @ 2021 Loglass Inc. 29
    1. 木構造を抽象化する
    2. mapのインターフェースを考える
    3. mapの実装をする
    # Tree.mapを作るまでのステップ

    View Slide

  30. @ 2021 Loglass Inc. 30
    # 3. mapの実装をする

    View Slide

  31. @ 2021 Loglass Inc. 31
    # 3. mapの実装をする
    自分自身に関数を適用
    さっきの 「1 -> “あ”」の関数

    View Slide

  32. @ 2021 Loglass Inc. 32
    # 3. mapの実装をする
    子供全員に再帰関数を
    適用する

    View Slide

  33. @ 2021 Loglass Inc. 33
    できた!

    View Slide

  34. @ 2021 Loglass Inc. 34
    全体像

    View Slide

  35. @ 2021 Loglass Inc. 35
    FIN

    View Slide

  36. @ 2021 Loglass Inc. 36
    ではない

    View Slide

  37. @ 2021 Loglass Inc. 37

    View Slide

  38. @ 2021 Loglass Inc. 38
    10000階層のツリー

    View Slide

  39. @ 2021 Loglass Inc. 39

    View Slide

  40. @ 2021 Loglass Inc. 40
    スタックオーバーフロー!!!

    View Slide

  41. @ 2021 Loglass Inc. 41
    # ⚠ここからは尺の関係上ざっくり説明します
    ● 全てを理解しようとしないでください
    ● あ〜こんなやり方あるんだな〜で大丈夫です
    👍
    ● コードはこちらです
    ○ https://github.com/YuitoSato/kotlin-sandbox/blob/master/src/main/kotlin/tree/Tre
    e.kt

    View Slide

  42. @ 2021 Loglass Inc. 42
    # 再帰関数におけるスタックオーバーフローとは
    ● 子の計算を全て終えないと親の関数が終わらない
    ○ 計算時の関数内ローカル変数をスタックに保持するが、そこがパンクする

    View Slide

  43. @ 2021 Loglass Inc. 43
    # では世の中の全ての再帰関数はスタックオーバーフローを起こすの?
    ● 言語によってはNo
    ● 一部の言語には末尾再帰最適化というものが実装されている

    View Slide

  44. @ 2021 Loglass Inc. 44
    # 末尾再帰最適化 (tail call optimization) とは~ ざっくり説明
    ● 一部のプログラムではビルド時に
    末尾呼び出しの再帰関数を単なる
    While文に最適化してい

    View Slide

  45. @ 2021 Loglass Inc. 45
    # これは末尾再帰

    View Slide

  46. @ 2021 Loglass Inc. 46
    # これは末尾再帰ではない
    最後に評価される関数は
    Treeのコンストラクタ

    View Slide

  47. @ 2021 Loglass Inc. 47
    別のやり方でやろう

    View Slide

  48. @ 2021 Loglass Inc. 48
    最適化が使えないので自力Whileをする

    View Slide

  49. @ 2021 Loglass Inc. 49
    # map処理のおさらい
    1
    2 4
    3
    5 6

    View Slide

  50. @ 2021 Loglass Inc. 50
    # map処理のおさらい

    2 4
    3
    5 6

    View Slide

  51. @ 2021 Loglass Inc. 51
    # map処理のおさらい

    い 4
    3
    5 6

    View Slide

  52. @ 2021 Loglass Inc. 52
    # map処理のおさらい

    い 4

    5 6

    View Slide

  53. @ 2021 Loglass Inc. 53
    # map処理のおさらい

    い え

    5 6

    View Slide

  54. @ 2021 Loglass Inc. 54
    # map処理のおさらい

    い え

    お 6

    View Slide

  55. @ 2021 Loglass Inc. 55
    幅優先探索だ!💡

    View Slide

  56. @ 2021 Loglass Inc. 56
    # 幅優先探索にはキュー(先に入れたものが先に出る)を使う
    1
    2 4
    3
    5 6
    処理待ちノードを入れるキュー
    優先処理
    1

    View Slide

  57. @ 2021 Loglass Inc. 57
    # 幅優先探索にはキュー(先に入れたものが先に出る)を使う

    2 4
    3
    5 6
    処理待ちノードを入れるキュー
    優先処理
    2
    3
    4
    1

    View Slide

  58. @ 2021 Loglass Inc. 58
    # 幅優先探索にはキュー(先に入れたものが先に出る)を使う

    い 4
    3
    5 6
    処理待ちノードを入れるキュー
    優先処理
    3
    4
    5
    6
    2

    View Slide

  59. @ 2021 Loglass Inc. 59
    # こう実装してみます

    View Slide

  60. @ 2021 Loglass Inc. 60
    # こう実装してみます
    キューと最終的に返す
    ツリーの初期化。

    View Slide

  61. @ 2021 Loglass Inc. 61
    # こう実装してみます
    キューから取り出して
    関数を適用

    View Slide

  62. @ 2021 Loglass Inc. 62
    # こう実装してみます
    処理したノードを
    最終的なツリーに足す

    View Slide

  63. @ 2021 Loglass Inc. 63
    # こう実装してみます
    次に処理されるノード(子
    供)をキューにいれる

    View Slide

  64. @ 2021 Loglass Inc. 64
    # こう実装してみます
    最後にリターン

    View Slide

  65. @ 2021 Loglass Inc. 65
    # イメージ: ① キューと空のツリーを用意する
    1
    2 4
    3
    5 6

    View Slide

  66. @ 2021 Loglass Inc. 66
    # イメージ: ② キューに積む
    1
    2 4
    3
    5 6
    1

    View Slide

  67. @ 2021 Loglass Inc. 67
    # イメージ: ③ キューの先頭に関数を適用する
    1
    2 4
    3
    5 6

    View Slide

  68. @ 2021 Loglass Inc. 68
    # イメージ: ④ キューの先頭を最終的なツリーに追加する
    1
    2 4
    3
    5 6

    View Slide

  69. @ 2021 Loglass Inc. 69
    # イメージ: ④ 子供を全てキューに積む
    1
    2 4
    3
    5 6

    2
    3
    4

    View Slide

  70. @ 2021 Loglass Inc. 70
    # イメージ: ①~④を繰り返す
    1
    2 4
    3
    5 6

    い え

    お か

    View Slide

  71. @ 2021 Loglass Inc. 71
    できた!(強引)

    View Slide

  72. @ 2021 Loglass Inc. 72
    今回のコードはこちらに全てあります。
    https://github.com/YuitoSato/kotlin-sandbox/blo
    b/master/src/main/kotlin/tree/Tree.kt

    View Slide

  73. @ 2021 Loglass Inc. 73
    # まとめ
    → 世の中にツリーは多い
    → ツリーのデータ変換は再帰関数が多くてつらい
    → map関数を作って再帰処理を隠蔽する
    → と思ったらスタックオーバーフローしてしまった
    → スタックオーバーフローを回避するために幅優先探索で実装する
    → ハッピー!

    View Slide

  74. @ 2021 Loglass Inc. 74
    ハッピー!(強引)

    View Slide

  75. @ 2021 Loglass Inc. 75
    # 余談: Q. スタックオーバーフローってどれくらいで起きるの? 🤔
    A. 手元のマシンで試したら10000階層くらいで発生した(※JVM内で格納しているスタックの量
    に寄ります)

    View Slide

  76. @ 2021 Loglass Inc. 76
    # 余談: Q. Loglassってそんな階層の深いツリーを扱うの?
    🤔
    A. 扱いません

    View Slide

  77. @ 2021 Loglass Inc. 77
    # 余談: Q. え、じゃあ幅優先探索の実装とか、必要、、?
    A. 要りません

    View Slide

  78. @ 2021 Loglass Inc. 78
    結論: ほぼほぼ再帰処理実装でOK(オチです)

    View Slide

  79. @ 2021 Loglass Inc. 79
    ありがとうございました!
    Kotlinで複雑なデータ構造に
    立ち向かいたい人Welcomeです!

    View Slide