Thiago Cafe - Programming is fun !  
Created by thiago on 2017-11-15 01:32:29

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.

References:

Any comments or questions, compliments ?

Reach me on twitter - @thiedri

...

Tell me your opinion!


Please prove you are human.
What is the result of addition of seven and 3 ?


Other comments

Thiago
on 2017-12-09

Testing comments with authentication !