Wednesday, July 14, 2010

Flipping text upside-down

Over the last few years, there has been a recurring meme to flip text upside-down. You can find posts about it, online text-flipping services, and programming libraries (e.g., for Perl and Emacs).

All of these implementations seem to work the same way: find Unicode characters that resemble upside-down version of the latin alphabet and create a mapping that is used to turn text "upside-down". Since Factor has strong support for Unicode, I thought it could use a library to flip strings.

What it should look like when we are done:

( scratchpad ) "abcdefghijklmnopqrstuvwxyz1234567890" flip-text .
"068Ɫ95ᔭƐᄅ⇂zʎxʍʌnʇsɹbdouɯʃʞɾᴉɥᵷɟǝpɔqɐ"

As is typical, we list our dependencies and create a namespace to hold the new functions:

USING: assocs kernel sequences ;

IN: flip-text

Next, we will create the character mapping (simply hard-coding the character lookups):

CONSTANT: CHARS H{
    { CHAR: a   HEX: 0250 }
    { CHAR: b   CHAR: q   }
    { CHAR: c   HEX: 0254 }
    { CHAR: d   CHAR: p   }
    { CHAR: e   HEX: 01DD }
    { CHAR: f   HEX: 025F }
    ...

And then, since it is useful to make the flip-text word reversible (e.g., return the original value if applied again), we will update the mapping with the reverse entries:

CHARS [ CHARS set-at ] assoc-each

Mapping a single character is pretty straight-forward (making sure to pass the original character through if a mapping isn't found):

: ch>flip ( ch -- ch' )
    dup CHARS at [ nip ] when* ;

And then flipping a string of text is just a matter of flipping each character and reversing the string:

: flip-text ( str -- str' )
    [ ch>flip ] map reverse ;

The complete implementation for this is on my Github account.

No comments: