240 likes | 354 Views
新しい再帰呼び出しの形式. Accumulator( 集積変数)を用いた再帰. 例:中間結果を保持して計算する. 相対距離から絶対距離. (50 40 70 30 30)から (50 90 160 190 220)を計算する. 相対距離. 0. 50. 40. 7 0. 30. 30. 絶対距離. 0. 50. 90. 160. 190. 220. relative-2-absolute. ;; relative-2-absolute : ;; (listof number) -> (listof number)
E N D
新しい再帰呼び出しの形式 • Accumulator(集積変数)を用いた再帰
例:中間結果を保持して計算する 相対距離から絶対距離 (50 40 70 30 30)から (50 90 160 190 220)を計算する 相対距離 0 50 40 70 30 30 絶対距離 0 50 90 160 190 220
relative-2-absolute ;; relative-2-absolute : ;; (listof number) -> (listof number) ;; 相対的距離を示す値のリストから ;; 絶対的距離を示す値のリストに変換する ;; リストの最初の要素は原点からの距離
relative-2-absolute (define (relative-2-absolute alon) (cond [(empty? alon) empty] [else (cons (first alon) (add-to-each (first alon) (relative-2-absolute (rest alon))))]))
add-to-each ;; add-to-each : number (listof number) -> (listof number) ;; リストalonの各要素に数nを加える (define (add-to-each n alon) (cond [(empty? alon) empty] [else (cons (+ (first alon) n) (add-to-each n (rest alon)))]))
relative-2-absoluteの性能評価 • (define x (relative-2-absolute (list 0 ... N))) 評価にかかる時間がNに比例しない.それ以上にかかる!
計算のトレース • 3,5,2,1,6 • 6 • 1,7 • 2,3,9 • 5,7,8,14 • 3,8,10,11,17 • Nの2乗に比例した計算(加算とcons)が必要
問題点 • これまでの値を記憶していない • 一つ前の値しかわからない
改良 • 3,5,2,1,6 • 3 • 3+5=8 • 8+2=10 • 10+1=11 • 11+6=17 • これをあわせて, • 3,8,10,11,17
rel-2-abs alon accu-dist (define (rel-2-abs alon accu-dist) (cond [(empty? alon) empty] [else (cons (+ (first alon) accu-dist) (rel-2-abs (rest alon) (+ (first alon) accu-dist)))])) Accumulator(集積変数)
計算のトレース • = (rel-2-abs (list 3 2 7) 0) • = (cons 3 (rel-2-abs (list 2 7) 3)) • = (cons 3 (cons 5 (rel-2-abs (list 7) 5))) • = (cons 3 (cons 5 (cons 12 (rel-2-abs empty 12)))) • = (cons 3 (cons 5 (cons 12 empty)))
完成したプログラム ;; relative-2-absolute2 : (listof number) -> (listof number) ;; 相対的距離を示す値のリストから ;; 絶対的距離を示す値のリストに変換する ;; リストの最初の要素は原点からの距離 (define (relative-2-absolute2 alon) (define (rel-2-abs alon accu-dist) (cond [(empty? alon) empty] [else (cons (+ (first alon) accu-dist) (rel-2-abs (rest alon) (+ (first alon) accu-dist)))])) (rel-2-abs alon 0))
Reverse ;; reverse : (listof X) -> (listof X) ;; to construct the reverse of alox (define (reverse alox) (cond [(empty? alox) empty] [else (make-last-item (reverse (rest alox))(first alox))])) リストの要素が逆転した新たなリストを作る
make-last-item ;; make-last-item : (listof X) X -> (listof X) ;;要素 an-x をリスト alox の最後につける (define (make-last-item alox an-x) (cond [(empty? alox) (list an-x)] [else (cons (first alox) (make-last-item (rest alox)an-x))]))
Reverseの問題点 • 再帰を2重に(reverse とmake-last-item) 行っている • (1 2 3 4 5 6)のreverse • () • (6) ; (make-last-item () 6) • (6 5) ; (make-last-item (6) 5) • (6 5 4) ; (make-last-item (6 5) 4) • (6 5 3 2) … • (6 5 3 2 1)
Accumulatorを用いたreverse • (1 2 3 4 5 6)のreverse • () • (1) • (2 1) • (3 2 1) • (4 3 2 1) • (5 4 3 2 1) • (6 5 4 3 2 1)
reverse ; reverse : (listof X) -> (listof X) ;; to construct the reverse of alox (define (reverse alox0) ;; accumulator is the reversed list of all those items ;; on alox0 that precede alox (define (rev alox accumulator) (cond [(empty? alox) ...] [else ... (rev (rest alox) ....... ) ... ])) (rev alox0 ...))
ACCを用いたreverse ー 完成版 ;; reverse : (listof X) -> (listof X) ;; to construct the reverse of alox (define (reverse alox0) ;; accumulator is the reversed list of all those items ;; on alox0 that precede alox (define (rev alox accumulator) (cond [(empty? alox) accumulator] [else (rev (rest alox) (cons (first alox) accumulator))])) (rev alox0 empty))
Accumulatorを用いた再帰に変換 ;; sum : (listof number) -> number ;; to compute the sum of the numbers on alon (define (sum alon) (cond [(empty? alon) 0] [else (+ (first alon) (sum (rest alon)))]))
ACCを用いたsum ;; sum : (listof number) -> number ;; to compute the sum of the numbers on alon0 (define (sum alon) (define (sum-a alon accumulator) (cond [(empty? alon) accumulator] [else (sum-a (rest alon) (+ (first alon) accumulator))])) (sum-a alon 0))
計算のトレース:通常の再帰 • (sum (list 10.23 4.50 5.27)) • = (+ 10.23 (sum (list 4.50 5.27))) • = (+ 10.23 (+ 4.50 (sum (list 5.27)))) • = (+ 10.23 (+ 4.50 (+ 5.27 (sum empty)))) • = (+ 10.23 (+ 4.50 (+ 5.27 0))) • = (+ 10.23 (+ 4.50 5.27)) • = (+ 10.23 9.77) • = 20.0
計算のトレース:ACCを用いた再帰 • (sum (list 10.23 4.50 5.27)) • = (sum-a (list 10.23 4.50 5.27) 0) • = (sum-a (list 4.50 5.27) 10.23) • = (sum-a (list 5.27) 14.73) • = (sum-a empty 20.0) • = 20.0
期末試験等 • 11月14日:演習のみ • 課題の最終締め切りは11月22日(木) • 11月21日:期末試験 • 3C113 8:40〜11:10 • プログラミングの問題 • これまでの課題と同じ方法で提出
期末試験:注意事項 • 問題は紙で配布 • 個人のノートPCは、使わないこと • 試験中に実行して良いソフトゥエア • DrRacket, エディタ, メール送受信のためのソフトウェア • ネットワークの使用は、解答の送受信に限る • ウェブの閲覧は禁止(ウェブメールを除く)等