Greek Time
July 8, 2016
So we don’t have to deal with the astronomical calculations, which are tricky, we assume you can find the sunrise and sunset times yourself. We did that in a previous exercise, but there seems to be a bug there, as (solar 38.6270 90.1994 2016 7 8 7)
returns sunrise at 29:45 instead of 5:45, so you might prefer to look at an almanac. We represent time as a pair containing hour and minute, and use this function to calculate the number of minutes between two times:
(define (duration start end) (when (< (cdr end) (cdr start)) (set! end (cons (- (car end) 1) (+ (cdr end) 60)))) (+ (* (- (car end) (car start)) 60) (- (cdr end) (cdr start)))) > (duration '(5 . 45) '(20 . 29)) 884
We also need a function to add a duration to a starting time:
(define (add-duration start duration) (let ((end (cons (+ (car start) (quotient duration 60)) (+ (cdr start) (modulo duration 60))))) (if (< (cdr end) 60) end (cons (+ (car end) 1) (- (cdr end) 60))))) > (add-duration '(5 . 45) 884) (20 . 29)
And now it’s easy to compute the hours:
(define (greek-time sunrise sunset) (let ((hour-length (/ (duration sunrise sunset) 12))) (map (lambda (dur) (add-duration sunrise dur)) (map (lambda (hour) (round (* hour hour-length))) (range 13))))) > (greek-time '(5 . 45) '(20 . 29)) ((5 . 45) (6 . 59) (8 . 12) (9 . 26) (10 . 40) (11 . 53) (13 . 7) (14 . 21) (15 . 34) (16 . 48) (18 . 2) (19 . 15) (20 . 29))
We used range
from the Standard Prelude. You can run the program at http://ideone.com/G5PwOK. Mark Dominus provides a somewhat different answer at his blog.