Wednesday, January 31, 2007

The Story of business_days(...)

I've been really busy with work recently. However, while going over my requirements for the nth time, something caught my eye: business days. In particular, finding the date 7 business days from a another date.

Far from being a hard task, it fell more into the annoying category. Or maybe it would make for a good interview question. In the end, how complicated or simple can someone make such a function?

A little background first. I had to use JavaScript, a language I'm only superficially familiar with. Also, after discussion with the customer, the definition of business days was Monday to Friday. No holidays are included... In fact, which holidays? And from what region/country?

Having flirted with Haskell recently and being "influenced" by the SICP lectures, a few ideas came to mind.

"business days" is a subset of "days", and both are infinitely lists. If I have a list of all the days and I filter it through the is_business_day(date) function, and I access the element at position 7, I get the answer. I was getting pretty angry with my inability to accomplish my task in such a straightforward way. I started to understand what people mean when they talk about the expressiveness of a programming language.

I then turned to Ruby for ideas. The succ function came to mind, I made that my starting point.
function include(value, list) {
for (var i=0; i < list.length; i++) {
if(list[i] == value) return true;
};
return false;
}

function succ(date) {
return new Date(date.getTime() + 1000 * 60 * 60 * 24);
}

function is_business_day(date) {
return include(date.getDay(), [1,2,3,4,5]); // mon-fri
}

function business_succ(date) {
var result = succ(date);
return is_business_day(result) ? result : business_succ(result);
}

function repeat(f, x, n) {
if(n == 1)
return f(x);

return f(repeat(f, x, n-1));
}

function days(date, n) {
return repeat(succ, date, n);
}

function business_days(date, n) {
return repeat(business_succ, date, n);
}
Personally, the moment of enlightenment came when I realized that iterating for days or business days was the same code and that it could be made even more generic by the repeat function.

A few comments:
  • the include function would usually be borrowed from prototype.js

  • recursion has become part of my day-to-day programming techniques

  • all functional

  • definitely not the shortest code I've written, but all pieces are both trivial and reusable

  • a definite LISP-like flavor

  • proof that SICP and friends have been damaging my brain :)

Thursday, January 04, 2007

I didn't "get" bookmarklets

I have only recently been fully aware of the joys of bookmarklets. Of course I had the del.icio.us bookmarklets for quite a while now, but, the idea had not fully sank in until recently. I didn't "get" bookmarklets.

Yesterday I re-discovered Google Reader and with it came its own, very useful, bookmarklet: Subscribe....

Today I decided to wrote my own: booktrack...

Booktrack is a web application to keep track of the books I read. It keeps track of what I want to read, what I'm reading now and what I'm done reading. This was inspired by librarything.com.

When it came to data entry, I had integrated with the amazon search API and it was working great. However, when people talk about books they usually link directly to the entry at amazon. Being on the page and having to log into my application to look for the exact same book seemed like a task that could be automated.

This was a spur-of-the-moment idea. A what-if that needed answering. 5 minutes later, I had it and it was working. It is relatively crude, but I'll take the iterative approach on this one.

Now I'm wondering what else I could do with that? What else needs a bookmarklet? What have I missed? This is all part of me trying to keep an eye out for stupid and repetitive tasks.