Schemeのプログラミング うるう年関連
Schemeで、
「(1)閏年かどうかを判定する関数leap?(number -> boolean)を定義した後、(2)○年○月の日数は何日かを求める関数num-of-days(number number -> number)を定義せよ」
という内容の課題を出されたのですが、(例えば 2009年の7月→31日 2012年の2月→29日)
どうもエラーが出て実行できません。
自分は以下のように組みました。
;;(1)の関数
(define (leap? year)
(cond
[(= (remainder year 400) 0) #t]
[(and (= (remainder year 4) 0)(> (remainder year 100) 0)) #t]
[else #f]
)
)
;;(2)の関数
(define (num-of-days year month)
(cond
[(and (= month 2)(= (leap? year) #t)) 29]
[(and (= month 2)(= (leap? year) #f)) 28]
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)
これを例えば
(num-of-days 2008 4) や (num-of-days 1995 12)
などとして実行すると、それぞれ30,31という正しい値を返してくれるのですが、
(num-of-days 2008 2) や (num-of-days 1995 2)
など、閏年・非閏年に関係無く、2月が絡むと
=: expects type <number> as 1st argument, given: false; other arguments were: true
というエラーを吐いてしまいます。
何度も見直しましたが、どこが間違っているのか見付けきれません…。どなたか間違いを指摘して頂けると幸いです。
No.3ベストアンサー
- 回答日時:
ああ、ちなみに。
manaka3161 さんの作ったコードのロジックは「無駄がある」とは思いますが、基本的に「間違ってはいない」、とは思いますよ。
どこが悪いのか?と言うと、単純に、ここです。
(define (num-of-days year month)
(cond
[(and (= month 2)(= (leap? year) #t)) 29] ;; ここが間違ってる
[(and (= month 2)(= (leap? year) #f)) 28] ;; ここが間違ってる
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)
「ロジックが合ってる」のに「エラーを返す」場合があるんです。何故なら、データ型に整合性がない、からです。
比較演算子=は「数値専用」で等価判定を下す。引数が数値である、ってのが前提なんですけど、引数にシンボル#tか#fが来てる、ってのがエラーの原因です。
> (= 1 2)
#f
> (= 1 1)
#t
> (= 'a 'b)
=: expects type <number> as 1st argument, given: a; other arguments were: b
=== context ===
/usr/lib/plt/collects/scheme/private/misc.ss:74:7
>
同じエラーですよね。見て分かる通り、=は数値しか引数に取れないんです。
つまり、シンボル同士を比較したい場合はeq?使った方が良いでしょう。すなわち、
(define (num-of-days year month)
(cond
[(and (= month 2)(eq? (leap? year) #t)) 29] ;二番目の判定式を eq? で行う
[(and (= month 2)(eq? (leap? year) #f)) 28] ;二番目の判定式を eq? で行う
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)
これで動く筈です。
> (num-of-days 2009 7)
31
> (num-of-days 2012 2)
29
>
慣れない内は、数値/シンボルの比較を両方「考えずに行いたい」のなら、eqv?を使った方が良いかもしれません。eqv?はリストじゃなければ数値/シンボルの両方とも行えます。eq?はシンボル専用、ですね。=は数値専用。
大まかに言うと、繰り返しになりますが、次のようになってます。
eq? => シンボル比較の時に使う。高速。
eqv? => 数値、シンボル両方O.K。ある意味デフォルト。
equal? => リスト同士まで比較出来る。ただし、eq?に比べると遅い。
= => 数値専用。
eq? => シンボル比較の時に使う。高速。
eqv? => 数値、シンボル両方O.K。ある意味デフォルト。
equal? => リスト同士まで比較出来る。ただし、eq?に比べると遅い。
= => 数値専用。
↑まさに私が求めていた解説でした!すごく分かり易くて、助かりました!
eq?を使用すれば、回りくどいけれども、あくまで自分の考えた内容でも通すことが出来るのですね。本当に有り難うございました。
No.2
- 回答日時:
;;; #t とか #f が返り値の場合、and や or 使った方がシンプル
(define (leap? year)
(and (zero? (modulo year 4))
(or (not (zero? (modulo year 100)))
(zero? (modulo year 400)))))
;;; こう言う場合、cond を使うとメンド臭いんで、case を使った方がシンプルに書けると思う
(define (num-of-days year month)
(case month
((1 3 5 7 8 10 12) 31)
((2) (if (leap? year) 29 28))
(else 30)))
caseはDrSchemeで認識してくれませんでした…。ですがifを使って補助関数を作成することで解決しました。有り難うございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
日齢計算プログラム
-
日付の差分の求め方(日、分)
-
Perlで日付を取得する
-
JSONで文字列が長い時
-
Application.ScreenUpdating = ...
-
formで特定のinputを送信しない...
-
HASH(0xほげほげ)
-
VBAでPDFのコピーとリネームを...
-
この曲のピアノの最後の和音が...
-
<SELECT>タグの折り返し
-
SELECT要素の垂直位置
-
VB6で、長い時間かかる処理...
-
ACCESS テキストボックスを隙...
-
関数「exists」と「defined」の...
-
16進の10進変換について
-
【至急!!!】python言語で本を見...
-
メールフォームを作成したいの...
-
【C#】数値の範囲チェックについて
-
インラインフレーム内へのリンク
-
FindFirst を複数条件で検索
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
おすすめ情報