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

再帰呼び出し / Python Recursion

kaityo256
PRO
November 15, 2022

再帰呼び出し / Python Recursion

プログラミング基礎同演習

kaityo256
PRO

November 15, 2022
Tweet

More Decks by kaityo256

Other Decks in Education

Transcript

  1. 1
    23
    再帰呼び出し
    プログラミング基礎同演習
    慶應義塾大学理工学部物理情報工学科
    渡辺

    View Slide

  2. 2
    23
    人口地図を作るプログラム
    nx, ny, nn = [], [], []
    for x, y, n in data:
    nx.append(x)
    nx.append(y)
    nn.append(n ** 0.5 * 0.3)
    plt.figure(figsize=(15, 15), dpi=50)
    plt.scatter(nx, ny, c=nn, s=nn, cmap=cm.seismic)
    ->
    ValueError: x and y must be the same size
    エラーが起きた場所
    エラーメッセージ
    (プロットする時はxとyは同じサイズでなければならない)
    実際に問題のあった場所

    View Slide

  3. 3
    23
    変数の中身を見てみる
    新しくセルを作り、nxを評価してみる 次にnyを評価してみると・・・
    あれ?空リストになっている
    nyへの数値のappendがされていない?
    nx, ny, nn = [], [], []
    for x, y, n in data:
    nx.append(x)
    nx.append(y)
    なんか大丈夫そう
    nyに値を入れているはずの場所を見てみる
    あっ →

    View Slide

  4. 4
    23
    エラーが起きる場所と
    バグを入れた場所は異なる
    デバッグには変数の評価が有効
    (print文デバッグ)

    View Slide

  5. 5
    23
    再帰呼び出し

    View Slide

  6. 6
    23
    再帰的定義:定義の記述に自分自身があらわれるもの
    フォルダ:その中にフォルダとファイルを含むもの
    A
    B B X
    Y
    Z

    View Slide

  7. 7
    23
    ある関数が、自分自身を呼び出すこと
    def func():
    func()
    上記のプログラムは、funcがfuncを呼び、呼び出さ
    れたfuncがまたfuncを呼び…と、実行が終わらない
    再帰呼び出しには、必ず終端条件が必要

    View Slide

  8. 8
    23
    自然数の階乗を返す関数fact(n)が作りたい
    def fact(n):
    a = 1
    for i in range(1, n+1):
    a *= i
    return a
    以下のようにループを回してしまうのが簡単だが、再帰で考えてみる

    View Slide

  9. 9
    23
    1. 再帰とは、自分自身を呼び出す関数である
    2. 関数の最初に「終端条件」を記述する
    3. 「解きたい問題より小さな問題」に分解して
    自分自身を呼び出す
    ※必ずしも上記に当てはまらない再帰もあるが、まずはこれが基本だと覚えること

    View Slide

  10. 10
    23
    「今解きたい問題よりも小さな問題の答えが全
    てわかっている場合、解きたい問題の答えはど
    う記述できるだろうか?」
    nの階乗fact(n)について、fact(n-1)の答えがわかっているなら、
    fact(n) = n * fact(n-1)
    階乗の場合:
    fact(n)
    fact(n-1)

    View Slide

  11. 11
    23
    fact(n) = n * fact(n-1)
    fact(n-1) = (n-1) * fact(n-2)
    ...
    fact(2) = 2 * fact(1)
    「分解」を繰り返すと、いつか「これ以上分解できない状態」に到達する
    終端条件
    ※ 0!=1としてfact(0)まで考えても結果は同じ
    ここでおしまい

    View Slide

  12. 12
    23
    def fact(n):
    if n == 1:
    return 1
    return n * fact(n-1)
    終端条件は(原則として)関数の最初に記述する
    終端条件

    View Slide

  13. 13
    23
    階乗を計算する関数
    def fact(n):
    if n == 1:
    return 1
    return n * fact(n-1)
    1. 定義中に自分自身を呼び出している
    2. 関数の最初に終端条件がある
    3. 「より小さな問題」として自分を呼びだす
    1. 再帰とは、自分自身を呼び出す関数である
    2. 関数の最初に「終端条件」を記述する
    3. 「解きたい問題より小さな問題」に分解して自分自身を呼び出す

    View Slide

  14. 14
    23
    def fact(n):
    if n == 1:
    return 1
    return n * fact(n-1)
    fact(3)
    fact(2)
    fact(1)
    呼び出し
    呼び出し
    ここで終端条件にマッチ
    fact(1) = 1
    fact(2) = 2 * fact(1)
    fact(3)ください
    fact(3) = 3 * fact(2) = 6
    再帰は「行って帰って」来る

    View Slide

  15. 15
    23
    1. 再帰とは、自分自身を呼び出す関数である
    2. 関数の最初に「終端条件」を記述する
    3. 「解きたい問題より小さな問題」に分解して
    自分自身を呼び出す
    再帰三カ条
    再帰は「行って帰って」来る
    fact(3)
    fact(2)
    fact(1)
    呼び出し
    呼び出し
    ここで終端条件にマッチ
    fact(1) = 1
    fact(2) = 2 * fact(1)
    fact(3)ください
    fact(3) = 3 * fact(2) = 6

    View Slide

  16. 16
    23
    3 = 1 + 1 + 1 3 = 1 + 2 3 = 2 + 1
    n段の階段を1段もしくは2段を混ぜて登る時、何通りの登り方があるか?
    n段の階段の登り方の数を返す関数 kaidan(n)が欲しい

    View Slide

  17. 17
    23
    3 = 1 + 1 + 1 3 = 1 + 2 3 = 2 + 1
    整数nを、1や2の和として表す方法の数
    3 = 1 + 1 + 1
    3 = 1 + 2
    3 = 2 + 1
    4 = 1 + 1 + 1 + 1
    4 = 1 + 1 + 2
    4 = 1 + 2 + 1
    4 = 2 + 1 + 1
    4 = 2 + 2
    kaidan(3) = 3 kaidan(4) = 5

    View Slide

  18. 18
    23
    再帰の考え方
    「今解きたい問題よりも小さな問題の答えが全
    てわかっている場合、解きたい問題の答えはど
    う記述できるだろうか?」
    階段を登り切る時は、最後に1段登る場合と2段登る場合がある
    n
    n-1
    n-2
    n
    n-1
    n-2
    kaidan(n) = kaidan(n-1) + kaidan(n-2)

    View Slide

  19. 19
    23
    再帰呼び出しには、必ず終端条件が必要
    階段の段数が1段や2段の場合には値を返す
    def kaidan(n):
    # 終端条件
    if 条件:
    return 値
    # 再帰部分
    return 自分自身を使った式
    最終的に関数はこんな形になる
    終端条件が二つあることに注意すること

    View Slide

  20. 20
    23
    迷路が与えられた時、スタートからゴールまでの道を知りたい
    • とりあえず進んで見る
    • 分かれ道に来たら、現在位置を覚えて適当に進む
    • もし行き止まりなら、先程の場所まで戻って別の道を試す
    基本的なアルゴリズム
    このように「とりあえず試して、ダメならやりなおす」
    というアルゴリズムをバックトラックと呼ぶ

    View Slide

  21. 21
    23
    とりあえず片方を試してみて、ダメなら戻る
    1
    2
    3 4
    5 6
    7
    将棋や囲碁の思考ルーチンに使われる
    数独等では「仮置き」と呼ばれる

    View Slide

  22. 22
    23
    1. 分かれ道に来た 2. とりあえず片方に進んで見る
    3. 行き止まりだったので戻る 4. まだ試してない道があれば進む

    View Slide

  23. 23
    23
    0
    1
    2
    0
    1
    2
    3
    3
    5
    4
    5
    6
    6
    7
    1. スタートからの距離を記録 2. 距離地図が完成する
    0
    1
    2
    3
    3
    5
    4
    5
    6
    6
    7
    0
    1
    2
    3
    3
    5
    4
    5
    6
    6
    7
    3. ゴールからカウントダウン 4. スタート地点まで到達したら完成

    View Slide