1 / 51

関数の組み立てと 補助関数

関数の組み立てと 補助関数. 今日は,複数の関数の組み合わせを学ぶ 関数 sort 関数 insert. リスト処理の再帰関数の本体定義. 基底ケース 再帰を含まない cond 節 定式化が容易 ,あるいは「例」により既知 ※ 「例」とは設計レシピでの「例」 自己参照のケース 関数の再帰的な適用 結果値の生成 部分 的な 結果 ( r est 部を使った自己適用 の結果) を使い, 最終結果を得る. この資料では,結果値の生成で, 補助関数を使う例を示す. ソート. ソート前 ( list 2 5 1 3 4 ) ソート後

manon
Download Presentation

関数の組み立てと 補助関数

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 関数の組み立てと補助関数

  2. 今日は,複数の関数の組み合わせを学ぶ 関数 sort 関数 insert

  3. リスト処理の再帰関数の本体定義 • 基底ケース • 再帰を含まないcond節 • 定式化が容易,あるいは「例」により既知 ※ 「例」とは設計レシピでの「例」 • 自己参照のケース • 関数の再帰的な適用 • 結果値の生成 部分的な結果(rest部を使った自己適用 の結果)を使い,最終結果を得る この資料では,結果値の生成で, 補助関数を使う例を示す

  4. ソート • ソート前 (list2 5 1 3 4) • ソート後 (list5 4 3 2 1) 要素の並び替え ※降順でのソートの場合 降順:大→小,昇順:小→大

  5. 問題の分析とデータの定義 入力:  数のリスト 出力 数のリスト  (ソート済み) 入力と出力の関係:  入力(数のリスト)の各要素を,降順に 並べなおしたものが出力 数のリスト(list of numbers)の定義 1.empty (空リスト) あるいは 2. (conse L) 但し, eは数(number)で, Lは数のリスト (list of numbers)

  6. 入力:  数のリスト 出力数のリスト(ソート済み) ※ 関数名は好きに付けてよいが,今回は sortとしている ;; sort : (listof number) ;; -> (listof number) (sorted) ;; alon 内の数から,降順にソートされた数のリストを生成 ;; (sort empty) -> empty ;; (sort (list 2 5 1 3 4)) ;; -> (list 5 4 3 2 1) (define (sort alon) ...)

  7. 数のリストを扱う再帰関数のテンプレート 基底ケース部分の定義を行う・・・ 基底ケース empty 入力が空リスト (empty) のとき, 出力も空リスト (empty) (define (sort alon) (cond [(empty?alon) ... ] [else ... (firstalon) ... (sort (restalon)) ... ]))

  8. [else ... (firstalon) ... (sort (restalon)) ... ])) 入力が空リスト (empty) で無い場合 例えば,入力が (list2 5 1 3 4) の場合 ■ 欲しい最終結果 (list5 4 3 2 1) 要素の並び替え これで,関数定義を考える (define (sort alon) (cond [(empty?alon) empty ] [else ... (firstalon) ... (sort (restalon)) ... ]))

  9. [else ... (firstalon) ... (sort (restalon)) ... ])) 例えば,入力が (list2 5 1 3 4)の場合 ■ 中間結果(sort (restalon)) は (restalon) -> (list5 1 3 4) になるので, (sort (restalon)) -> (list5 4 3 1) になるはず ■ 欲しい最終結果 (list5 4 3 2 1) 中間結果を使って, どう,最終結果を得るか (firstalon) -> 2 最終結果を得るには,(firstalon)の値 2 を中間結果 (list5 4 3 1)に挿入

  10. [else ... (firstalon) ... (sort (restalon)) ... ])) [else (insert (firstalon) (sort (restalon))) ]))  関数定義の完成 ※ (first alon) を,降順でソート済みの数のリスト(sort (rest alon))の適切な場所に挿入 → そのために,補助関数 (Auxiliary Function) を定義    (ここでは,関数名 insert) (firstalon) -> 2 最終結果を得るには,(firstalon)の値 2 を中間結果 (list5 4 3 1)に挿入

  11. 補助関数 insert を用いた,関数 sort の定義 ;; sort : (listof number) -> (listof number) (sorted) ;; alon 内の数から,降順にソートされた数のリストを生成 ;; (sort empty) -> empty ;; (sort (list 2 5 1 3 4)) ;; -> (list 5 4 3 2 1) (define (sort alon) (cond [(empty?alon) empty] [else (insert (firstalon) (sort (restalon)))])) 基底ケース 補助関数を使用 これで,関数 sortの定義は終わり

  12. 主関数と補助関数 主関数 sort 処理を頼む! 結果 呼び出す側 必要なデータ 補助関数 insert 呼び出される側 複数の関数に「分割」

  13. 主関数 sortの定義は終わったので,insertに移る • 関数 insertの定義では consが登場する

  14. 問題の分析とデータの定義今度は関数 insert 入力:  数と 数のリスト (ソート済み) 出力 数のリスト (ソート済み) 入力と出力の関係:  数を,降順でソート済みの数のリストに挿入し,新しい数のリストを作る 入力として与えられる数のリストは, すでに降順でソート済みである と考える

  15. 入力:  数と 数のリスト(ソート済み) 出力数のリスト(ソート済み) ※ 関数名は好きに付けてよいが,今回は insert としている ;; insert : number (listof number)(sorted) ;; -> (listof number)(sorted) ;; 数 n と,降順にソート済みの数のリスト alon から, ;; 降順にソート済みの数のリストを生成する ;; (insert 5 empty) -> (list 5) ;; (insert 2 (list 5 4 3 1)) ;; -> (list 5 4 3 2 1) (define (insert n alon) ...)

  16. ヘッダ (define (insert n alon) ... ) 数のリストを扱う再帰関数のテンプレート テンプレートは,ヘッダで 定めた関数名 insert と, パラメータ名 n, alon にあわ せて調整 基底ケース 自己適用を含む Scheme 式 ※ セレクタrestの結果値へ自己適用 (define (insert n alon) (cond [(empty?alon) ...] [else ... (firstalon) ... (insert n (restalon)) ... ]))

  17. 数のリストを扱う関数のテンプレートをもとに数のリストを扱う関数のテンプレートをもとに 基底ケース部分の定義を行う 基底ケース (cons n empty) 入力が空リスト (empty) のとき, 出力は, (cons n empty) (define (insert n alon) (cond [(empty?alon) ... ] [else ... (firstalon) ... (insert n (restalon)) ... ]))

  18. [else ... (firstalon) ... (insert n (restalon)) ... ])) 数のリストを扱う関数のテンプレートをもとに 基底ケース部分の定義を行う 基底ケース alonが空リストで無い場合 結果値は,nも含み,alonの全要素を含む数のリスト(降順でソート済み) (cons n empty) 入力が空リスト (empty) のとき, 出力は, (cons n empty) (define (insert n alon) (cond [(empty?alon) ... ] [else ... (firstalon) ... (insert n (restalon)) ... ]))

  19. nが alonの全要素よりも大きいとき n = 7, alon = (list6 5 4)のとき   ■ 最終結果 (insert nalon) -> (list7 6 5 4)   ⇒ これは (consn alon) 最終結果 ※ n を先頭要素として,新しいリストを作る • nが alonの全要素よりも大きいか? • 全要素を調べる必要はない  • nが (firstalon)より大きいか,等しいかを調べるだけ. alonは降順にソート済みだから

  20. nよりも大きな数を alonが含むとき n = 3, alon = (list6 2 1 -1)のとき ■ 最終結果 (insert n alon)-> (list6 3 2 1 -1) • これは数のリスト.nを含むとともに,alonの全要素を含む • nを, 先頭要素の前に挿入してはいけない • nを,alon内のどこに挿入するかを探す処理が必要

  21. nよりも大きな数を alonが含むとき n = 3, alon = (list6 2 1 -1)のとき ■ 最終結果 (insert n alon)-> (list6 3 2 1 -1) • nは (restalon)内のどこかに挿入される • (cons (firstalon) (insertn (restalon))) (firstalon)-> 6 (insertn (restalon)) -> (list3 2 1 -1) 中間結果 最終結果 nが (firstalon)よりも小さい場合の処理

  22. nが (firstalon)より大きいか,等しい場合 • nが (firstalon)よりも小さい場合 場合分けには,Scheme の cond文を使用 (cond [(>=n (firstalon)) ...] [(<n (firstalon)) ...])

  23. ;; insert: number (listof number)(sorted) ;; -> (listof number)(sorted) ;; 数 n と,降順にソート済みの数のリスト alon から, ;; 降順にソート済みの数のリストを生成する ;; (insert 5 empty) -> (list 5) ;; (insert 2 (list 5 4 3 1)) -> (list 5 4 3 2 1) (define (insert n alon) (cond [(empty?alon) (consnempty)] [else (cond [(>=n (firstalon)) (consn alon)] [(<n (firstalon)) (cons (firstalon) (insert n (restalon)))])]))

  24. 複数の関数の組み合わせ • 関数 sort • 関数 insert ;; sort : (listof number) ;; -> (listof number) (sorted) (define (sort alon) (cond [(empty?alon) empty] [else (insert (firstalon) (sort (restalon)))])) 規約に合致 ;; insert: number (listof number)(sorted) ;; -> (listof number)(sorted) ※ 規約に合致しなければ実行時エラー

  25. 実習

  26. 実習の進め方 資料を熟読 「実習」と書いてあるページでは,実習の手順に従って,各自で実行する.理解を深める それぞれの「実習」では,実行結果を付けているので,確認しておく 26

  27. DrScheme の使用 DrScheme の起動 プログラム → PLT Scheme → DrScheme 今日の演習では「Intermediate Student」 に設定 Language → Choose Language → Intermediate Student → Run ボタン 27

  28. 例題1.要素の挿入 • ソート済み(整列)のリストに,整列関係を保ったままで,要素を挿入する関数 insert • ここでは,要素が降順にソート済みとする • 挿入を行うために,consを使う 降順にソート済みのリスト 要素 (80 21 10 7 5 4 3 1) 40 (80 40 21 10 7 5 4 3 1)

  29. 入力と出力 (list 80 21 10 7 5 4) 40 (list 80 40 21 10 7 5 4) insert 出力 入力 入力は,数と ソート済みの数のリスト 出力は要素挿入後の ソート済みの数のリスト

  30. 実習1 • 「定義ウインドウ」で,次の関数定義を行いなさい • 関数名 insert, パラメータ n, alon • 入力した後に,Run ボタンを押す ;;insert : number (listof number) (sorted) ;; -> (listof number) (sorted) ;; 数 n と,降順にソート済みの数のリスト alon から, ;; 降順にソート済みの数のリストを生成する ;; (insert 5 empty) -> (list 5) ;; (insert 2 (list 5 4 3 1)) -> (list 5 4 3 2 1) (define (insert n alon) (cond [(empty?alon) (consnempty)] [else (cond [(>=n (firstalon)) (consn alon)] [(<n (firstalon)) (cons (firstalon) (insert n (restalon)))])])) 2. その後,次の式を「対話ウインドウ」で評価させなさい (insert40 (list80 21 10 7 5 4))

  31. 関数 insert 評価結果 31

  32. 実習2 • 「定義ウインドウ」の中身を次のように書き換えて,もう1度評価させなさい • 入力した後に,Run ボタンを押す 実習1と同じ ;;insert : number (listof number) (sorted) ;; -> (listof number) (sorted) ;; 数 n と,降順にソート済みの数のリスト alon から, ;; 降順にソート済みの数のリストを生成する ;; (insert 5 empty) -> (list 5) ;; (insert 2 (list 5 4 3 1)) -> (list 5 4 3 2 1) (define (insert n alon) (cond [(empty?alon) (consnempty)] [else (cond [(>=n (firstalon)) (consn alon)] [(<n (firstalon)) (cons (firstalon) (insert n (restalon)))])])) (insert20 (list80 21 10 7 5 4)) 1行書き加える • 2. その後,DrScheme を使って,ステップ実行の様子を • 確認しなさい  (Step ボタンを使用) •  理解しながら進むこと 32

  33. (insert 20 (list 80 21 10 7 5 4))から (list 80 21 20 10 7 5 4))を得る過程の概略 (insert20 (list80 21 10 7 5 4)) → … → (cons80 (insert20 (rest (list80 21 10 7 5 4)))) → (cons80 (insert20 (list21 10 7 5 4))) → … → (cons80 (cons21 (insert20 (list10 7 5 4))) → … → (cons80 (cons21 (list20 10 7 5 4))) → (list80 21 20 10 7 5 4) 33

  34. 実習3. インサーションソート 実習1のinsertを補助関数として使い、数のリストを降順にソートする関数sortを作る 出力はソート済み の数のリスト 入力は数のリスト sort (list3 5 1 4) (list1 3 5 7 10 21 4 80) →(list5 4 3 1) →(list80 21 10 7 5 4 3 1)

  35. 実習3 • 「定義ウインドウ」で,次の関数定義を行いなさい • 入力した後に,Run ボタンを押す ;; sort: (listof number) -> (listof number)(sorted) ;; alon 内の数から,降順にソートされた数のリストを生成 ;; (sort empty) -> empty ;; (sort (list 2 5 1 3 4)) -> (list 5 4 3 2 1) (define (sort alon) (cond [(empty?alon) empty] [else (insert (firstalon) (sort (restalon)))])) ;; insert : number (listof number) (sorted) ;; -> (listof number) (sorted) ;; 数 n と,降順にソート済みの数のリスト alon から, ;; 降順にソート済みの数のリストを生成する ;; (insert 5 empty) -> (list 5) ;; (insert 2 (list 5 4 3 1)) -> (list 5 4 3 2 1) (define (insert n alon) (cond [(empty?alon) (consnempty)] [else (cond [(>=n (firstalon)) (consn alon)] [(<n (firstalon)) (cons (firstalon) (insert n (restalon)))])])) 実習1 と同じ

  36. 実習3 (続き) 2. その後,次の式を「対話ウインドウ」で評価させなさい (sort(list3 5 1 4)) (sort(list1 2 1 3 1 2)) (sortempty)

  37. 評価結果

  38. (sort (list 3 5 1 4)) から (list 5 4 3 1)) が得られる過程の概略 (1/2) (sort (list 3 5 1 4)) = … = (insert 3 (sort (rest (list 3 5 1 4)))) = (insert 3 (sort (list 5 1 4))) = … = (insert 3 (insert 5 (sort (rest (list 5 1 4))))) = (insert 3 (insert 5 (sort (list 1 4)))) = … = (insert 3 (insert 5 (insert 1 (sort (rest (list 1 4)))))) = (insert 3 (insert 5 (insert 1 (sort (list 4))))) = … = (insert 3 (insert 5 (insert 1 (insert 4 (sort (rest (list 4))))))) = (insert 3 (insert 5 (insert 1 (insert 4 (sort empty))))) = … = (insert 3 (insert 5 (insert 1 (insert 4 empty)))) 次ページへ

  39. (sort (list 3 5 1 4)) から (list 5 4 3 1)) が得られる過程の概略 (1/2) (sort (list 3 5 1 4)) = … = (insert 3 (sort (rest (list 3 5 1 4)))) = (insert 3 (sort (list 5 1 4))) = … = (insert 3 (insert 5 (sort (rest (list 5 1 4))))) = (insert 3 (insert 5 (sort (list 1 4)))) = … = (insert 3 (insert 5 (insert 1 (sort (rest (list 1 4)))))) = (insert 3 (insert 5 (insert 1 (sort (list 4))))) = … = (insert 3 (insert 5 (insert 1 (insert 4 (sort (rest (list 4))))))) = (insert 3 (insert 5 (insert 1 (insert 4 (sort empty))))) = … = (insert 3 (insert 5 (insert 1 (insert 4 empty)))) これは, (define (sortalon) (cond [(empty? alon) empty] [else (insert (first alon) (sort (rest alon)))])) の alonを (list 3 5 1 4) で置き換えたもの 次ページへ

  40. (sort (list 3 5 1 4)) から (list 5 4 3 1)) が得られる過程の概略 (2/2) = (insert 3 (insert 5 (insert 1 (insert 4 empty)))) = … = (insert 3 (insert 5 (cons 4 (insert 1 (rest (list 4)))))) = (insert 3 (insert 5 (cons 4 (insert 1 empty)))) = … = (insert 3 (insert 5 (cons 4 (cons1 empty)))) = … = (insert 3 (cons 5 (list 4 1))) = … = (cons 5 (insert 3 (list 4 1))) = … = (cons 5 (cons 4 (insert 3 (list 1))) = … = (cons 5 (cons 4 (cons 3 (list 1))) = (list 5 4 3 1)

  41. 実習4. 並べ替え方の変更 実習1,2のinsert,sortを書き換えて,「数字の下2桁の昇順」で並び替えるようにする 出力はソート済み の数のリスト 入力は数のリスト sort (list101 205 301 403) →(list101 301 403 205)

  42. 実習4 (1/3) 変更箇所 • 「定義ウインドウ」の中身を次のように書き換えて,もう1度評価させなさい ;; sort: (listof number) -> (listof number)(sorted) ;; alon 内の数から,下2桁で昇順にソートされた数のリストを生成 ;; (sort empty) -> empty ;; (sort (list 101 205 301 403)) -> (list 101 301 403 205) (define (sort alon) (cond [(empty?alon) empty] [else (insert (firstalon) (sort (restalon)))])) 関数 sortの定義は変更しない(そのまま使う)

  43. 実習4 (2/3) 2. 「定義ウインドウ」の中身を次のように書き換えて,もう1度評価させなさい ;; insert : number (listof number) (sorted) ;; -> (listof number) (sorted) ;; 数 n と,下2桁で昇順にソート済みの数のリスト alon から, ;; 下2桁で昇順にソート済みの数のリストを生成する ;; (insert 5 empty) -> (list 5) ;; (insert 205 (list 301 404)) -> (list 301 403 205) (define (insert n alon) (cond [(empty?alon) (consnempty)] [else (cond [(<= (remaindern 100) (remainder (firstalon) 100)) (consn alon)] [else (cons (firstalon) (insert n (restalon)))])])) 変更箇所 43 ※remainderは、ある数をある数で割った余りを求める

  44. 実習4 (3/3) 3. その後,次の式を「対話ウインドウ」で評価させなさい (sort(list3 5 1 4)) (sort(list1 2 1 3 1 2)) (sort(list101 205 301 403)) (sortempty)

  45. 実習5.構造体のソート p3d構造体が次のように定義されている x フィールドの値で,昇順にソートするように,実習4の関数 sortと insertを書き換える (define-struct p3d(x y z)) (参考) ・p3d構造体のコンストラクタ (make-p3d ... ...) ・p3d構造体のセレクタ (p3d-x ...),(p3d-y ...),(p3d-z ...) ※p3d-x, p3d-y, p3d-zがセレクタ 46 46

  46. 実習5 (1/4) 1. 「定義ウインドウ」で,次の構造体定義と変数定義を行いなさい (define-structp3d (x y z)) (defineZ (list (make-p3d0 0 0) (make-p3d3 2 3) (make-p3d1 5 2) (make-p3d2 4 3))) 47

  47. 実習5 (2/4) 変更箇所 2. 「定義ウインドウ」で,次の関数定義を行いなさい ;; sort: (listof p3d) -> (listof p3d)(sorted by x) ;; p3d 構造体のリストを,xフィールドの値で昇順にソート ;; (sort empty) -> empty (define (sort alop) (cond [(empty?alop) empty] [else (insert (firstalop) (sort (restalop)))])) 変数名は alop (A List Of P3d) に変えている 48

  48. 実習5 (3/4) 3. 「定義ウインドウ」で,次の関数定義を行いなさい ;; insert : number (listof p3d) (sorted by x) ;; -> (listof p3d) (sorted by x) ;; 数 n と,xフィールドの値で昇順にソート済みの p3d リスト alop から, ;; xフィールドの値で昇順にソート済みの数のリストを生成する (define (insert p alop) (cond [(empty?alop) (conspempty)] [else (cond [(<= (p3d-xp) (p3d-x (firstalop))) (consp alop)] [else (cons (firstalop) (insert p (restalop)))])])) 変更箇所 49

  49. 実習5 (4/4) 4. その後,次の式を「対話ウインドウ」で評価させなさい (sortZ) (sortempty) 50

More Related