現実の問題を扱うプログラム 現実の問題は複雑 問題が数式で簡潔に書かれていることは少ない 冗長な情報が含まれていたり,プログラムを作る 上で必要な情報が含まれていないことがある 問題分野の知識が必要とされる 例題:簡単な「現実」の問題 東海道新幹線で東京を発車して新大阪に到 着する列車の一番列車は東京を6時に出て, 新大阪に8時25分に到着するのぞみ1号であ る.次の列車は東京を6時16分に出て,新大 阪に8時43分に到着するのぞみ3号である. のぞみ3号は,東京から552.6キロメートル離 れた新大阪にいく最高速のぞみに比べると新 大阪に到着するのに2分よけいにかかる.東 京から新大阪へ行く最も高速な列車の時速を 計算するプログラムを作成せよ. (注: 故意にわかりにくくしている) 問題の分析 問題文はあいまいで、わかりにくい 東京から新大阪へ行く最高速の新幹線列車の 時速を計算すること 何を求めるのかはっきりさせる これには、東京と新大阪の間の距離と最高速列車の 所要時間がわかればよい 不要な情報 列車番号 問題領域の知識 東海道新幹線ではのぞみが最高速の列車であ る 時速=距離/所要時間 専門家の間では常識となっていることもプログラムを 書く人は知らないことが多い 目的を書く ;; velocity : distance hour -> velo ;; distance : number ;; hour : number ;; velo : number ;; velocity はdistance/hour で定義される ;; example: (velocity 1000 5) = 200 (define (velocity distance hour) (/ distance hour)) プログラム作成法 1. 2. 3. 4. 5. 6. 7. 問題を理解する プログラムで行うべきことを書き下す 型の宣言をする ;; velocity : distance hour -> velo ;; distance : number ;; hour : number ;; velo : number 目的を書く 理解を助ける入出力の例を示す プログラムの本体を書く テストをする 続き ;; 一時間は60分であることを定義している (define min-in-hour 60) ;; 手続き(関数) h:m-to-hは時間と分を与えて,時間を計算する ;; 例: (h:m-to-h 1 30) => 1.5, ;; なぜならば,1時間30分は1.5時間である. (define (h:m-to-h hour min) (+ hour (/ min min-in-hour))) 続き ;; 以下のプログラムは最高速の列車の時速を 計算する ;; 東京と新大阪の距離は552.6である (- (h:m-to-h 8 43) (h:m-to-h 6 16) (h:m-to-h 0 2)) (velocity 552.6 (- (h:m-to-h 8 43)(h:m-to-h 6 16) (h:m-to-h 0 2))) 条件式 条件に基づいて,計算の道筋を変更する 条件式の基となる概念 真理値(trueとfalse) 真は#t,偽は#f 述語 述語は真理値を値とする関数 (= 4 5) (< 5 4) (and (= x y) (< y z)) (or (= x y) (> y z)) (not (= x y)) (define (between-5-6? n)(and (< 5 n) (< n 6))) 関数 cinterval-3-9? (define (cinterval-3-9? n) (and (<= 3 n) (< n 9))) 条件式の一般形 (cond [question answer] ... [question answer] ) あるいは (cond [question answer] ... [else answer] ) 条件式の例 (cond [(<= n 1000) 0.040] [(<= n 5000) 0.045] [(<= n 10000) 0.055] [(> n 10000) 0.060]) 上から条件を見ていくことに注意 条件式の例 (cond [(<= n 1000) 0.040] [(<= n 5000) 0.045] [(<= n 10000) 0.055] [else 0.060]) 条件式を用いるプログラム例 実数を係数とする二次方程式 a x**2 + b x + c=0 の実根の数を求める (how-many a b c) ==> 二次方程式の実根の数 how-many ; how-many : number number number-> number ;; how-many は二次方程式の実数根の数を返す ;;二次方程式a x**2 + b x + c= 0は係数a, b, cで与え る 続き ;; 二次方程式 a x**2 + b x + c = 0 が与えられたとする ;; ここで, aは0でないとする ;; 実根の数は 2 if b**2 > 4 a c ;; 1 if b**2 = 4 a c ;; 0 if b**2 < 4 a c ;; 例: (how-many 1 0 -1) = 2 ;; (how-many 2 4 2) = 1 ;; a = 0の時はプログラムは 文字列“error” を返す (define (how-many a b c) ..) (define (how-many a b c) (cond [(= a 0) "error"] [else (cond [(= (determinant a b c) 0) 1] [(> (determinant a b c) 0) 2] [(< (determinant a b c ) 0) 0])])) 続き ;; determinant: number number number -> number ;; 判別式 b**2 - 4 a c を計算する (define (determinant a b c) (- (* b b) (* 4 a c))) 記号 (シンボル) 記号は引用符が先頭についた文字の列 人工知能の研究のために導入された 例 'the, 'dog, 'How-are-you? 文字列とは異なる "the", "dog", "How are you?" 記号 ー 続き もっとも基本的なデータ構造でこれ以上分割できない 基本的な操作は、比較のみ (eq? 'Morning 'Morning) (eq? 'Morning 'Evening) 記号を用いたプログラム例 次のような挨拶に答えるプログラムを作成する 'GoodMorning ==> 'Hi 'HowAreYou? ==> 'Fine 'GoodAfternoon ==> 'INeedANap 'GoodEvening ==> 'BoyAmITired プログラムの骨子 ;; reply : symbol -> symbol ;; 挨拶 s の返答を返す (define (reply s) ...) 対話をするプログラム (define (reply s) (cond [(eq? s 'GoodMorning) 'Hi] [(eq? s 'HowAreYou?) 'Fine] [(eq? s 'GoodAfternoon) 'INeedANap] [(eq? s 'GoodEvening) 'BoyAmITired])) 簡単な通訳プログラム (define (interpret s) (cond [(eq? s 'GoodMorning) 'おはよう] [(eq? s 'HowAreYou?) '元気?] [(eq? s 'GoodAfternoon) '今日は] [(eq? s 'GoodEvening) '今晩は]))
© Copyright 2024 ExpyDoc