Sunday, August 14, 2011

Human Numbers

I noticed a project on Github called slang.js. It includes a number of "string utility" functions that might be useful to Javascript developers. One that struck me as interesting was the humanize function for turning numbers into "humanized" strings such as "1st, 2nd, 3rd or 4th".
Note: this function is sometimes called "ordinalize" - for example, in the django.contrib.humanize module or the inflector python project.
We are going to translate this original version into Factor:
function humanize(number) {
    if(number % 100 >= 11 && number % 100 <= 13)
        return number + "th";

    switch(number % 10) {
        case 1: return number + "st";
        case 2: return number + "nd";
        case 3: return number + "rd";
    }

    return number + "th";
}
If we keep the same structure (although, without the advantage that early returns can provide), it looks like this:
: humanize ( n -- str )
    dup 100 mod 11 13 between? [ "th" ] [
        dup 10 mod {
            { 1 [ "st" ] }
            { 2 [ "nd" ] }
            { 3 [ "rd" ] }
            [ drop "th" ]
        } case
    ] if [ number>string ] [ append ] bi* ;
And, then build some tests to make sure it works.
[ "1st" ] [ 1 humanize ] unit-test
[ "2nd" ] [ 2 humanize ] unit-test
[ "3rd" ] [ 3 humanize ] unit-test
[ "4th" ] [ 4 humanize ] unit-test
[ "11th" ] [ 11 humanize ] unit-test
[ "12th" ] [ 12 humanize ] unit-test
[ "13th" ] [ 13 humanize ] unit-test
[ "21st" ] [ 21 humanize ] unit-test

No comments: