How many days have I lived ?
In a dinner conversation, my youngest daughter was curious about how many days had she lived so far. I told her that it is easy to calculate for a baby but not for her, though I could easily implement it.
She was still curious, but when I told her that I'm more than 1000
years days old (she guessed a bit more than 10), excited, they asked me to implement right away!
Am I getting old ?
I decided to implement in python my first version. Very expressive language. And this was my first version.
def show(name, y, m, d): cur = datetime.now() dt = datetime(y, m, d) dty = datetime(cur.year, m, d) if dty > cur: dty = datetime(cur.year-1, m, d) print( name ) print( ' ', cur-dt ) print( ' ', (cur.year-y), 'years', cur-dty ) print( '------------------------------' )
And it did the trick. After that, I decided to play a bit and implemented in hy-lang, a lisp flavoured python. That was the version
(defn show-age [name y m d] (setv cur (datetime.now)) (setv dt (datetime y m d)) (setv dty (datetime cur.year m d)) (cond [(> dty cur) (setv dty (datetime (- cur.year 1) m d))]) (print name) (print " " (- cur dt)) (print " " (- cur.year y) "years" (- cur dty)) (print "------------------------------"))
Well, it actually looks quite good. Super expressive and succint as the python version, but without the annoying indenting as block delimiter. Specially annoying when different editors use different configs. This is a better python, actually.
Let's stop with polemic conversations.
I decided then, to implement in a more lisp-like language. Let's see the Racket version. First of all, this sequential lisp is not very lispy, therefore I had to break up and better organize my code.
I needed the functions (extracted from the previous code)
Counting days in a date range
(define (diff-dates f s) (- (->jdn s) (->jdn f))) (define (how-old-days bday cur-date) (diff-dates bday cur-date))
What is the last birthday - to get the number of years
(define (get-last-bday bday cur-date) (let ([last-bday (date (->year cur-date) (->month bday) (->day bday))]) (if (date>? last-bday cur-date) (date (- (->year cur-date) 1) (->month bday) (->day bday)) last-bday)) )
How many years and days in a date range
(define (how-old-year bday last-bday cur-date) (list (- (->year last-bday) (->year bday)) (diff-dates last-bday cur-date) ) )
And finally, I have to write the results
(define (show-age name y m d) (let* ( [bday (date y m d)] [cur-date (->date (now))] [last-bday (get-last-bday bday cur-date)] [num-days (how-old-days bday cur-date)] [year-and-day (how-old-year bday last-bday cur-date)] ) (begin (displayln name) (printf " ~a days\n" num-days) (printf " ~a years ~a days\n" (car year-and-day) (cadr year-and-day)) (displayln "------------------------------") ) ))
The code is much better and organized. I have to admit that my first python/hy-lang versions are quite readable and quick to implement, but this last version is super clear and nice.
Or maybe I just need to learn how to write better python and hy-lang.
Any comments or questions, compliments ?
Reach me on twitter - @thiedri
Testing comments with authentication !