problem 19

Problem 19 - Project Euler

20 世紀中に一日が日曜日である月が何回あるかという問題です。
日付を扱うモジュールがあるからそれを使って瞬殺でしたが、モジュールを使うの禁止といわれたら今の自分には無理な問題でした。

(use srfi-19)

;; y 年 m 月 d 日の曜日を返す
(define (get-wday d m y)
  (date-week-day (make-date 0 0 0 0 d m y (date-zone-offset (current-date)))))

(define (p19)
  (let loop ((y 1901)
             (m 1)
             (result 0))
    (if (= y 2001) result
      (loop (if (= m 12) (+ y 1) y)
            (if (= m 12) 1 (+ m 1))
            (if (= (get-wday 1 m y) 0) (+ result 1) result)))))

(print (p19))

分かったこと

  • 日付関連のモジュールは srfi-19
  • make-date で date オブジェクトをつくる
  • date-week-day は date オブジェクトを受け取り曜日を返す。
  • 他にも日付の操作はいろいろ srfi-19 にあるみたい。

if 式をどこに入れるか

scheme って全部式で if も値を返すので、どこでも if を書けるのが面白いです。上記だと loop の引数とか。
で、どう書くのが「っぽい」んでしょうか。例えば、件の部分であれば

      (loop (+ y (if (= m 12) 1 0))
            (+ 1 (if (= m 12) 0 m))
            (+ result (if (= (get-wday 1 m y) 0) 1 0))))))

とも書けるわけで。好みだとは思いますが。