第4回
条件式と条件関数

例題

情報処理演習II

例題１．月の日数

入力と出力 月 month を受け取り(数字)、その日数を求める関数 easy-get-num-of-days を作る。
ただし、うるう年のことは考えない。
– まず月ごとに12通りに分けて考えてみよ131
easy-get-num-of-days
出力

入力– 日数は3通りしかない。3つの節を持つ cond 式で考えよ– 比較演算と論理演算を組み合わせる

easy-get-num-of-days 関数「関数である」ことを示すキーワード

関数の名前(define (easy-get-num-of-days month)(cond[(= month 2) 28][(or (= month 4) 値を１つ受け取る（入力）(= month 6)(= month 9)(= month 11)) 30][else 31]))

出力は１つの数値

入力は１つの数値

easy-get-num-of-days 関数節(define (easy-get-num-of-days month)(cond[(= month 2) 28][(or (= month 4)(= month 6)(= month 9)(= month 11)) 30][else 31]))1

easy-get-num-of-days 関数の実行例(1/2)

easy-get-num-of-days 関数の実行例(2/2)
ここでは、(easy-get-num-of-days 1)と書いて、month の値を 1に設定しての実行実行結果である「31」が表示される

まず、関数を定義している

例題２. うるう年の判定
 西暦年 year から、うるう年であるかを求グレゴリオ暦でのうるう年
 うるう年とは：める関数 is-leap? を作り、実行する

365.2422日
– うるう年の判定のために、比較演算と論理演算を組み合わせる– 西暦年が 4、 100、 400 の倍数であるかを調べる
ために remainder を使う例）

２００１→ うるう年でない

２００４→ うるう年である

うるう年の判定法– 4の倍数の年ならうるう年– 但し、100の倍数の年で400の倍数でない年はうるう年ではない(4の倍数だが例外)• 2005年はうるう年でない(4の倍数でない)• 2004年はうるう年(4の倍数)• 2000年はうるう年(100の倍数で例外にも当てはまらない)• 1900年はうるう年でない(4の倍数で100の倍数だが400の倍数でないので例外に相当)– 年がある数の倍数かを調べるためremainderを使う

うるう年の判定式

入力と出力(or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0)))400の倍数である

100の倍数でない

2月が29日まである年

 うるう年は400年に97回で、1年の平均日数は2005

false
is-leap?

4の倍数である
入力

出力かつまたは出力はtrue あるいは false 値2is-leap? 関数「関数である」ことを示すキーワード

関数の名前

is-leap? 関数
値を１つ受け取る（入力）

節(define (is-leap? year)(cond[(or (= (remainder year 400) 0)(and (not (= (remainder year 100) 0))(= (remainder year 4) 0))) true][else false]))(define (is-leap? year)(cond[(or (= (remainder year 400) 0)(and (not (= (remainder year 100) 0))(= (remainder year 4) 0))) true][else false]))is-leap? 関数の実行例(1/2)

is-leap? 関数の実行例(2/2)
今度は、(is-leap? 2005)と書いて、year の値を 2005に設定して実行

まず、関数を定義している実行結果である「false」が表示される

例題３. 曜日を求める

ツエラーの公式(数式表現)

 西暦の年、月、日から曜日を求める公式である

ツエラー(zellar)の公式のプログラムを作る。
– ツエラーの公式では「1年の起点を3月とし、月は3月から14月まである」と考えている。（うるう年があるので、1年の起点を3月とする方が計算が簡単）– 1月、2月は、前年の13月、14月と考え、月は3から14までの数になる。
– 計算された曜日は「数字」で次の意味になる。
012

3456

日曜

月曜

火曜

水曜

木曜

金曜

土曜

[(y+[y/4]+[y/400]-[y/100]+[(13m+8)/5]+d) mod 7]

ここで y: 年、 d: 日、m: 月(3月を起点とする月
で値は3から14までの値をとる(1月、2月は前年の13、14月と考える)）
 この計算の結果値が0なら日曜、1なら月曜・・・
 式中 [...] とあるのは、小数点以下切り捨て
 modは剰余を計算。例えば 2005 mod 4 は 13

remainder remainder の意味：

– 割り算の余りを求める– (remainder x y) はツエラーの公式の x mod y に対応

ツエラーの公式のプログラム

quotient

 quotient の意味：

– 整数の割り算の商を求める– (quotient x y) は、ツエラーの公式の [x / y] に対応

ツェラーの公式の実行例(1/2)[(y+[y/4]+[y/400]-[y/100]+[(13m+8)/5]+d) mod 7](define (zellar̲f y m d)(remainder(+ y(quotient y 4)
(quotient y 400)(- (quotient y 100))(quotient (+ (* 13 m) 8) 5)d)7));; zellar : number number number -> number;; to determine youbi (the day of the week) from year, month, and day.
;; The result is 0 ... 6 meaning 0 is Sunday, 1 Monday, and so on(define (zellar y m d)(cond[(or (= m 1) (= m 2)) (zellar̲f (- y 1) (+ m 12) d)][else (zellar̲f y m d)]))

まず、関数を定義しているツェラーの公式の実行例(2/2)(zellar 2005 5 5)と書いて、yの値を2005、mの値を5、dの値を5に設定して実行する

実習

実行結果である「4(木曜日)」が表示される

4DrScheme の使用

実習の進め方 資料を見ながら、「実習」を行ってみる

 DrScheme の起動

プログラム → PLT Scheme → DrScheme その後、各自、「課題」に挑戦する– 各自で自習 ＋ 巡回指導
– 遠慮なく質問してください 今日の実習では「Intermediate Student」に設定
Language 自分のペースで先に進んで構いません→ Choose Language→ Intermediate Student→ OK ボタン

DrScheme の使用 / ステップ実行

実習１．条件関数のステップ実行

 プログラム実行の振る舞いを観察するツール

 関数 easy-get-num-of-days （例題１）につい 「定義用ウインドウ」のみを使用（通常の実行と異なる）
 「Intermediate Student」に設定する必要あり
Language → Choose Language→ Intermediate Student→ OK ボタン「実習１．条件関数のステップ実行」の手順
1. 次を「定義用ウインドウ」で、実行しなさい••

Intermediate Student で実行すること入力した後に、Run ボタンを押す(define (easy-get-num-of-days month)
例題１(condと同じ[(= month 2) 28][(or (= month 4)(= month 6)(= month 9)
ステップ実行したい(= month 11)) 30]
ので、定義用ウインドウ[else 31]))だけを使う(easy-get-num-of-days 1)
2. DrScheme を使って、ステップ実行の様子を確認しなさい （Step ボタン、Next ボタンを使用）• 理解しながら進むことて、実行結果に至る過程を見る– (easy-get-num-of-days 1) から 31 に至る過程
を見る– DrScheme のステップ実行機能を使用(define (easy-get-num-of-days month)(cond[(= month 2) 28][(or (= month 4)(= month 6)(= month 9)(= month 11)) 30][else 31]))(easy-get-num-of-days 1) から 31 に至る過程 (1/3)(easy-get-num-of-days 1) 最初の式
= (cond(cond[(= 1 2) 28][(= month 2) 28][(or (= 1 4)[(or (= month 4)(= 1 6)(= month 6)に month = 1 が代入される(= month 9)(= 1 9)(= month 11))(= 1 11)) 30] 30][else 31]))[else 31]))= (cond[false 28][(or (= 1 4)(= 1 2) → false(= 1 6)(= 1 9)(= 1 11)) 30][else 31]))= (cond[(or (= 1 4)(= 1 6)[false 28] → 消える(= 1 9)(= 1 11)) 30]
コンピュータ内部での計算[else 31]))5

(easy-get-num-of-days 1) から 31 に至る過程 (2/3)= (cond[(or false
コンピュータ内部での計算(= 1 6)(=14)→ false(= 1 9)(= 1 11)) 30][else 31]))= (cond[(or (= 1 9)
false → 消える(= 1 11)) 30][else 31]))= (cond[(or false(= 1 9) → false(= 1 11)) 30][else 31]))= (cond[(or (= 1 11)) 30] false → 消える[else 31]))= (cond[(or false) 30](= 1 11) → false[else 31]))

実習２．条件関数のステップ実行
 関数 is-leap? （例題２）について、実行結果に至る過程を見る– (is-leap? 2005) から false に至る過程を見る– DrScheme のステップ実行機能を使用(define (is-leap? year)(cond[(or (= (remainder year 400) 0)(and (not (= (remainder year 100) 0))(= (remainder year 4) 0))) true][else false]))(easy-get-num-of-days 1) から 31に至る過程 (3/3)= (cond(or false) → false[false 30][else 31]))コンピュータ内部での計算= 31 出力結果「実習２．条件関数のステップ実行」の手順
1. 次を「定義用ウインドウ」で、実行しなさい••

Intermediate Student で実行すること入力した後に、Run ボタンを押す

例題２と同じ(define (is-leap? year)(cond[ (or (= (remainder year 400) 0)(and (not (= (remainder year 100) 0))(= (remainder year 4) 0))) true][else false]))ステップ実行したい(is-leap? 2005)
ので、定義用ウインドウだけを使う
2. DrScheme を使って、ステップ実行の様子を確認しなさい （Step ボタン、Next ボタンを使用）• 理解しながら進むこと(is-leap? 2005) から true が得られる過程 (1/3)
最初の式(is-leap? 2005)= (cond(cond[(or (= (remainder year 400) 0)[(or (= (remainder 2005 400) 0)(and (not (= (remainder year 100) 0))(and (not (= (remainder 2005 100) 0)) [else false])(= (remainder year 4) 0))) true](= (remainder 2005 4) 0))) true] に year = 2005 が代入される[else false]))= (cond[(or (= 5 0)(and (not (= (remainder 2005 100) 0))(= (remainder 2005 4) 0))) true] (remainder 2005 400) → 5[else false]))= (cond[(or false(and (not (= (remainder 2005 100) 0))(= 5 0) → false(= (remainder 2005 4) 0))) true][else false]))コンピュータ内部での計算(is-leap? 2005) から true が得られる過程 (2/3)= (cond[(or (and (not (= (remainder 2005 100) 0))(or false 式) → (or 式)(= (remainder 2005 4) 0))) true][else false]))= (cond(remainder 2005 100) → 5[(or (and (not (= 5 0))(= (remainder 2005 4) 0))) true][else false]))= (cond[(or (and (not false)(= (remainder 2005 4) 0))) true] (= 5 0) → false[else false]))= (cond[(or (and true(= (remainder 2005 4) 0))) true] (not false) → true[else false]))コンピュータ内部での計算

6

(is-leap? 2005) から true が得られる過程 (3/3)= (cond[(or (and (= (remainder 2005 4) 0))) true](and true 式) → (and 式)[else false]))= (cond[(or (and (= 1 0))) true] (remainder 2005 4) → 1[else false]))= (cond[(or (and false)) true] (= 1 0) → false[else false]))= (cond[(or false) true](and false) → false[else false]))= (cond(or false) → false[false true]
コンピュータ内部での計算[else false]))= false
実行結果

課題

課題１


課題２

x = 5 のとき、次の Scheme の式の実行結
果は何であるか、答えなさい– 実際に DrScheme で実行しなさい– true あるいは false の値である
1. (> x 1)
2. (and (> 10 x) (> x 1))
3. (= x (* x x))

次の値を求める関数 foo2 を定義し、実行結果を報告しなさい– 「X mod 7」 は、X を 7 で割った時の余り（剰余）。
例えば 2005 mod 7 は 3 である。
– remainderを使いなさい。

[(20x + 8) / 7] mod 10
式中の [...] は、小数点以下切り捨てを意味する。

課題３

課題４．月の日数関数 foo2 を定義し、実行結果を報告しなさい 年 year （数値）と，月 month （数値）を受け取り，– cond を使うことその日数を求める関数 get-num-of-days を定義
し，実行結果を報告しなさい．
– うるう年のことも考慮せよ

５０グラム以下なら７５グラム以下なら１００グラム以下なら１５０グラム以下なら→ １２０→ １４０→ １６０→ ２００

例えば，2004年の2月は29日まである– 例題１の easy-get-num-of-days と例題２の is-leap? を適切に利用する

7

課題のヒント ここにあるのは「間違い」の例です。同じ間違いをしないこと。
１．関数名の付け方の間違い(define (decide price w)... 以下省略⇒ 「decide price」では無く、「decide̲price」のように１単語で書くこと２．≦、≧をプログラム中に使うことはできない⇒ 代わりに、<=、 >= を使うこと

8