よりClojureらしく閏年を探す

Clojure入門がてらに「初心者用課題」を解いてみる - 蟲!虫!蟲! - #!/usr/bin/bugrammerの第二問を解いて、解説を加えたものです。

前回(よりClojureらしい素数列 - OGINO Masanori@はてな)を踏まえた説明なので、前回を読んでいない方はそちらを先に読んでください。

どこかで見た構造

前回を読んでいれば、素数列のコードと今回の閏年のコードの構造の類似点は容易に発見できると思います。

leap-year?はグレゴリウス暦グレゴリオ暦)の閏年の定義そのものなので、解説する所は特にありません。

練習問題
  • 400で割り切れる場合
  • 400で割り切れないが、4でも100でも割り切れる場合
  • 400でも100でも割り切れないが、4で割り切れる場合
  • 400でも100でも4でも割り切れない場合

Clojureのコードを読み慣れていない方は、どの場合でも真偽値が返ってくるかどうか考えると読解の練習になるかもしれません。述語の存在を意識するのが要点です。

やっぱりどこかで見た構造

leap-yearsは前回のprime-numbersとほとんど同じですが、1582個もの要素を捨てています。

これは、グレゴリウス暦は1582年に制定されたらしいので、0*1から1581まで飛ばしただけです。飛ばさなくても今回のような練習問題では問題ありません。

1582個もの要素を計算して使わずに捨てるのはもったいないと思う方*2は、rangeのコードを表示して読んでみてください。1582から始まる無限シーケンスを作るヒントが見つかると思います。(見つからなかったら質問してください。)

(source range)

おわりに

同じような問題は、きっと同じようなコードで解けます。でも、違ったコードで解けるかもしれません。

第三問のBuzzFizz(FizzBuzzFizzとBuzzの条件を逆転させたもの?)は、無限シーケンスを使うようにする以外に提示する意義のある方法が特にない*3と思うので、スキップします。

次回はよりClojureらしく線形合同法を使った乱数列を計算する - OGINO Masanori@はてなです。

あまり読まれないものと思っていましたが、問い合わせがあって少し驚きました。ありがとうございます。

*1:西暦0年は存在しません。

*2:私は書きながら「ちょっともったいないかな」と思いました。

*3:コードゴルフは今回の趣旨から離れますし、私はコードゴルフが得意ではありません。