Archive for December, 2005

Birthday Notes

Birthday Notes is an application with two purposes. On one hand it provides an easy way to keep track of people’s birthdays on Mac OS X. The other role it plays is to learn Cocoa programming using Python, Cocoa and PyObjC.

Why bother with yet another birthday tracking tool? Quite simply, most were too difficult to get the information that I wanted. The main aim of Birthday Notes is to provide a list of upcoming birthdays with relevant information.

For example, I rarely think of people’s birthdays in terms of their birth date (eg 1977-08-04). My brain is wired so that I remember that my birthday is on the 4th of August and that I’m currently 28 and turning 29 on my next birthday. Rather than show the birth date, Birthday Notes shows the birthday and the person’s age they turn on that day.

Birthday Notes features integration to Apple’s existing applications for storing data. This means that iSync support comes for free. The current focus is on a maintenance and reporting tool, so you can edit a person’s birthday from within Birthday Notes, but not create or delete. For additional actions, simply double click on the person’s name - they will be revealed in AddressBook.

I like to know some trivia about people’s birthdays, so Birthday Notes includes a bit of useless astrological information.

Birthday Notes is available for download. Requires OS X 10.4 or greater.

Any thoughts, suggestions, bugs or feedback should be sent to gmwils AT pseudofish.com, or posted in comments on this post.

For those interested in the code, it is available under a GPL license. To compile, Python 2.4, a recent build of PyObjC, and icalendar are needed.

Finally, my thanks to those who have been helping with alpha testing. This release marks the start of a public beta.

Target (redux)

After having spent some of last week solving the Target word problem using Haskell, I thought I might try another language.

C++ is one of those languages that retains low level control and simple machine semantics while providing high abstraction levels. The first language I learnt, it is also the one I’ve used the most. I usually skip it for attempting to understand an algorithmic problem, but once the algorithm is well understood it can make a big speed difference.

As I’ve been pondering this from a productivity point of view, the interesting bit is how I approached the problem. Fortunately, C++ includes pseudo functional constructs via the STL. This meant that I could keep a reasonable level of abstraction. Loops replaced recursion, as it is technically possible to use recursion in C++, it just doesn’t feel right.

The time spent building the C++ version was around the same time as for the Haskell version. When run against a large dictionary of words (234937), the Haskell version took around 4.5 seconds, with the C++ version taking just less than a second.

I believe there is still some optimisation space left in both programs.

Given a similar problem, I would pick Haskell to explore, even with a slower result. For some reason, it was more fun to program against.

To continue this, I’m going to pick a trickier problem and try implementation in multiple languages. In theory, there is a Cocoa to Haskell binding …

For future reference, my code looks like:


#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <set>

using namespace std;

bool containsWord(char const&, string const&, string const&);
bool includesAllLetters(string const &, string const &);

int main(int argc, char** argv) {
    string from, word;
    char letter;

    if(argc < 4) {
        cout << "usage: mainChar allLetters wordListn";
        return 0;
    }

    letter = argv[1][0];
    word = argv[2];
    from = argv[3];

    ifstream is(from.c_str());
    istream_iterator<string> ii(is), eos;

    int count = 0;
    vector<string> targets;
    cout << "Words: ";
    for( ; ii != eos; ++ii)
        if(containsWord(letter, word, *ii)) {
            cout << *ii << " ";
            ++count;
            if(word.length() == (*ii).length()) targets.push_back(*ii);
        }
    cout << "n";
    cout << "Found " << count << " words.n";

    cout << "Targets: ";
    for(vector<string>::iterator p = targets.begin(); p!=targets.end(); ++p)
        cout << *p << " ";
    cout << "n";

    return !is.eof();
}

bool containsWord(char const& c, string const &word, string const &testWord) {
    if(testWord.length() < 4 || testWord.length() > word.length() || testWord.find(c) == testWord.npos) return false;

    if(includesAllLetters(word, testWord)) return true;

    return false;
}

bool includesAllLetters(string const &word, string const &testWord) {
    string letters(word);
    for(string::const_iterator p = testWord.begin(); p !=testWord.end(); ++p) {
        size_t loc = letters.find(*p);
        if(loc == letters.npos)
            return false;
        else
            letters.erase(loc, 1);
    }
    return true;
}

Paul Graham: What Languages Fix

Paul has an interesting article about describing languages:

Kevin Kelleher suggested an interesting way to compare programming languages: to describe each in terms of the problem it fixes.

I’d like to add to his list:

  • Haskell: Lisp doesn’t have types
  • Mercury: Prolog doesn’t have types and requires too much knowledge of the internals

There should be a nice concise summary of Objective-C, but as I’ve been avoiding it I’ve struggled to come up with one. It doesn’t solve the problem of C being too low level. The closest I could get was that it added Object Oriented programming concepts to C.

Bruce - Presentation software using PyGame

Richard Jones has posted Bruce, the presentation software he used at the recent OSDC.

Various presentation software was used during the conference along with many presentation styles. The ones that stuck out the most were the typical corporate slides in PowerPoint. Usually, as I feel asleep or played on my laptop during these. Presentation Zen needs to be read by many presenters, especially if they missed Paul’s presentation.

The presentation that had the greatest impact at showing live code was Richard’s using Bruce. With PyGame as a back end, there was no application swapping between the demo and the slides. The demos were contained within the slides!

Another interesting presentation platform was Autrijus’s. His talk was built using XUL, the scripting platform created by the Mozilla team. The slides he used are available on his site and you need to follow the link using Firefox to view them. He has even been referenced (unattributed) by a site listing their top five speakers!

s/Monad/Action/g

Autrijus gave a wonderful talk on Haskell at OSDC. One insight that must be shared:

Everywhere you see Monad, replace it with Action in your head.

Monads are conceptually quite tricky. This simple insight is an “ahha!” moment. Several years of studying (and teaching) Haskell at Uni and this clarified the concept like no other tutorial.