Spectrum.vim – My first Vim plugin

Over the past few months, I’ve been using Vim as my primary development tool at work and at home, and I have to say, I’m addicted to it! I’m thinking about writing a blog post of why I get hooked on “walking without crutches”, but for this post, I’m just going to introduce you to my first plugin in Vim – Spectrum.


Spectrum is a vim colorscheme roulette. Ever getting tired of staring at the same colorscheme every day? Having hundreds of colorschemes in your repo but too lazy to deterministically pick one? Spectrum helps you by randomly pick colorschemes from your vim runtime path or from the web. From there, you have the chance of voting up a colorscheme so Spectrum will have a higher probability to pick it or voting down a colorscheme so you wouldn’t see it again.


To be honest, I’m not a fan of Vim script – the language is not very expressive and doesn’t have a lot of object oriented features. Semi-fortunately, since Vim 7, they have added support for Python, Ruby and Perl scripts. I said ‘semi-fortunately’ because the support isn’t too comprehensive. For most core vim features, you still have to resort to calling Vim commands to achieve them, but at least I don’t have to use Vim script for the most part.

Spectrum is written in Python, and use the “vim“ module to interact with the hosting Vim instance. There is a bit of bootstrapping to do if you want to separate most of the Python code out of the entry point vim script (see https://github.com/kevinjqiu/spectrum.vim/blob/master/plugin/spectrum.vim). Many vim plugins written in Python require you to install the python code into your Python runtime before you can use them, but for a simple module like Spectrum, I opted for monkey patching syspath to include modules in the plugin folder.

Anyhow, give it a try and hope you like it.


Use Python decorator to curry functions

It’s been a while since the last time I wrote about Python. This morning, I was listening to a podcast on my way to work. They were discussing functional programming and dynamic languages…I learned Python before I went into Computer Science, and then I learned about functional programming and through learning of Scala and Clojure, my functional programming concepts have been enriched. As I was listening, it suddenly appeared to me that there isn’t a way in Python to curry a function. Not that it’s critical to everyday development, but wouldn’t it be neat if I can curry a function in Python?

Then the hosts of the podcast discussed how dynamic languages are so flexible that you can pretty much do anything to it. “You can take a function as parameter, return a function from a function, and so on.” Hey, isn’t that what Python’s decorator can do? I learned decorators before, but I haven’t used it beyond the scope of creating properties and certainly haven’t written any decorators. I thought this would be a good exercise for learning decorators.

Here’s a simple example of what function currying: suppose you have a method

def add(x,y):
  return x+y

Then calling add(1,2) should be the same as add(1)(2). add(1) is what they call a partially applied function. It’s a function that takes one parameter.

Our goal here is to write a decorator “curried” that takes a function with n parameters and transform it in a way that can be applied n times and get the final result.

We’ll start with unit tests first:

import unittest

class CurryTest(unittest.TestCase):

	def test_with_no_args(self):
		def do_nothing():
			return ""
		self.assertEquals("", do_nothing())

	def test_with_int_args(self):
		def add_int(x,y):
			return x+y
		self.assertEquals(3, add_int(1)(2))
	def test_with_str_args(self):
		def add_str(x,y):
			return "%s%s"%(x,y)
		self.assertEquals("ab", add_str("a")("b"))

So we make sure that a currying on a function takes no parameter is valid but should be a pass through, and also the “curried” decorator can be applied to any function with arguments (excluding positional arguments and keyword arguments)

A decorator is simply a function that takes a function as parameter:

def curried(fn):

and @curried is simply a syntactic sugar for:

def fn(...): ...

So, now we can write “curried” decorator.
To make the test for function with no argument pass, in curried() function, we can test to see if fn has arguments. Python’s standard library provides inspect.getargspec method:

def curried(fn):
  argspec = inspect.getargspec(fn)
  if len(argspec.args)==0:
    return fn
    # later

Now the first test passes.

For the other two cases, here’s the strategy. In Python, when a class defines __call__ method, the instance of that class is said to be “callable”. For instance:

class A(object):
  def __call__(self, arg):
    return arg

f("echo")  # this gives you "echo"

This is very similar to Scala’s apply() function. Now that we have this in our inventory, we can define a `PartialFunction` class, take all the required parameters of the original function, and allow them to be applied one at a time. So the __call__ method of PartialFunc will look like this:

def __call__(self, value):
  # Xxx

If all the required parameters are passed in, PartialFunc should evaluate the original function with the complete argument list. Otherwise, PartialFunc stores the parameter in an instance variable, and returns itself.

Here’s the complete code:

class PartialFunc(object):
	def __init__(self, fn, argspec):
		self.fn = fn
		self.argspec = argspec 
		self.args = []

	def __call__(self, value):
		if len(self.args) == len(self.argspec.args):
			arglist = ",".join(["self.args[%d]"%i for i in range(0, len(self.args))])
			return eval("self.fn(" + arglist + ")")
			return self

and the curried decorator:

def curried(fn):
	argspec = inspect.getargspec(fn)
	if len(argspec.args) == 0:
		return fn
		return PartialFunc(fn, argspec)

It’s pretty straightforward. When the parameters are complete, I construct a python statement that calls the original function with the complete argument list, and then pass the statement into an eval statement. I know evals are evil, but I can’t find a way in Python to dynamically change the signature of the original method and make it accept a variable length argument (varargs).

So this is it. It’s quite simple. Python methods can have varargs and keyword args, the situation gets a little more complicated. The thing is, both varargs and keyword args are not mandatory, so it’s hard for the curried function to know whether the argument list has been completed…Also, if you take default values into account, it could get even more complicated.

(Python) Enable Auto-complete in a PDB session

Pretty simple actually…Just put the following code in ~/.pdbrc and then you can use the Tab key during a PDB session to see the available attributes of the current context.

import rlcompleter

Hexspeak word list

BAFFLED            BAFF1ED
LIFE               11FE
ASSAILS            A55A115
SILLIES            51111E5
SEEDED             5EEDED
BASEBALLS          BA5EBA115
ACED               ACED
SISAL              515A1
BEFALL             BEFA11
CLEO               C1E0
BAFFLES            BAFF1E5
FALL               FA11
ACES               ACE5
DILLS              D1115
SAILED             5A11ED
BLAB               B1AB
CLEF               C1EF
CODAS              C0DA5
ABODE              AB0DE
LASS               1A55
FACIALS            FAC1A15
DALLAS             DA11A5
EASES              EA5E5
ADDLED             ADD1ED
SADDLE             5ADD1E
DODO               D0D0
EDDIE              EDD1E
EDIFIES            ED1F1E5
ALDO               A1D0
COLLOIDS           C01101D5
LASSIE             1A551E
CALFS              CA1F5
SCOFFED            5C0FFED
CASES              CA5E5
FOALS              F0A15
ADDLES             ADD1E5
COBBLES            C0BB1E5
ABBESSES           ABBE55E5
ILLS               1115
LOSS               1055
LELA               1E1A
COLLOID            C01101D
FOAL               F0A1
LABELS             1ABE15
BELLIED            BE111ED
ASSESSES           A55E55E5
ASSESS             A55E55
LADDIES            1ADD1E5
FEDS               FED5
SABLE              5AB1E
ASSESSED           A55E55ED
BELLIES            BE111E5
BODE               B0DE
EDIFICES           ED1F1CE5
LEASE              1EA5E
DECODED            DEC0DED
DIAL               D1A1
SCAFFOLDS          5CAFF01D5
LOBED              10BED
SOFIA              50F1A
ABLES              AB1E5
LASSA              1A55A
LOBES              10BE5
FIDO               F1D0
CEDILLAS           CED111A5
DECODES            DEC0DE5
SLICES             511CE5
BOOBED             B00BED
LASSO              1A550
OLDIE              01D1E
CODE               C0DE
LIEFS              11EF5
CODA               C0DA
SEAS               5EA5
DACCA              DACCA
DEEDS              DEED5
FOIBLE             F01B1E
LOOSES             1005E5
CABBIES            CABB1E5
COIFS              C01F5
SOLACED            501ACED
CODS               C0D5
SEAL               5EA1
EBOLA              EB01A
BILLED             B111ED
FOLD               F01D
BAILS              BA115
DOLLS              D0115
BLOBBED            B10BBED
FOIBLES            F01B1E5
ISABELLA           15ABE11A
LIED               11ED
ISABELLE           15ABE11E
BEEFED             BEEFED
FEASIBLE           FEA51B1E
BESIDE             BE51DE
LIBIDO             11B1D0
OFFICIALS          0FF1C1A15
LOSE               105E
SOBS               50B5
ACIDIC             AC1D1C
ACCEDES            ACCEDE5
ALLIE              A111E
COOS               C005
FLAIL              F1A11
LOAF               10AF
FLOSSED            F1055ED
BABE               BABE
SOLI               5011
DOLES              D01E5
SOLD               501D
ELSA               E15A
ELSE               E15E
CASALS             CA5A15
DISCOED            D15C0ED
LESLIE             1E511E
FLAB               F1AB
ASSAIL             A55A11
DISCO              D15C0
SOLS               5015
COOL               C001
DECEASE            DECEA5E
SLIDE              511DE
SAID               5A1D
OODLES             00D1E5
CLASSICAL          C1A551CA1
ALOE               A10E
SIDED              51DED
SAIL               5A11
CICADAE            C1CADAE
DOODADS            D00DAD5
BLOC               B10C
BLOB               B10B
LEAFS              1EAF5
DOODLE             D00D1E
SELLS              5E115
OILFIELD           011F1E1D
ELISEO             E115E0
FEED               FEED
CODES              C0DE5
ELLIS              E1115
FACIAL             FAC1A1
ADIDAS             AD1DA5
BASSES             BA55E5
DEFIES             DEF1E5
CEASELESS          CEA5E1E55
CASED              CA5ED
ELLIE              E111E
LEOS               1E05
CODED              C0DED
LIBS               11B5
DADDIES            DADD1E5
FILLIES            F1111E5
ACID               AC1D
DEFIED             DEF1ED
DOSED              D05ED
EDSEL              ED5E1
SLEDDED            51EDDED
LOBBIES            10BB1E5
SOILED             5011ED
CECILIA            CEC111A
CACAOS             CACA05
DILLED             D111ED
DIDO               D1D0
BLESSED            B1E55ED
DAIS               DA15
CASIO              CA510
CEASE              CEA5E
DOSES              D05E5
BLESSES            B1E55E5
BOOBS              B00B5
BODIES             B0D1E5
ALOES              A10E5
FILES              F11E5
SCAB               5CAB
BLOBS              B10B5
CEASES             CEA5E5
ISOSCELES          1505CE1E5
LODES              10DE5
BASSO              BA550
ELLA               E11A
ACIDS              AC1D5
DEICED             DE1CED
BASSI              BA551
ISABEL             15ABE1
IBIS               1B15
SCABS              5CAB5
ELLS               E115
DIALS              D1A15
DEICES             DE1CE5
SOCIABLE           50C1AB1E
SOLIS              50115
AILS               A115
OSSIFIES           0551F1E5
CASELOAD           CA5E10AD
CICADAS            C1CADA5
SLID               511D
LABELED            1ABE1ED
ACCESSES           ACCE55E5
BABELS             BABE15
SOLIDS             5011D5
SCALDED            5CA1DED
LAOS               1A05
BLOODLESS          B100D1E55
SEED               5EED
CALCIFIES          CA1C1F1E5
CLOD               C10D
AISLE              A151E
LOBBED             10BBED
CALLS              CA115
CODDED             C0DDED
LELIA              1E11A
SOIL               5011
COLOSSI            C010551
CEASED             CEA5ED
SALABLE            5A1AB1E
BAOBABS            BA0BAB5
LOLLS              10115
FOSSILS            F055115
SECEDES            5ECEDE5
SLICED             511CED
LOOSE              1005E
AIDED              A1DED
BLADED             B1ADED
FLOODS             F100D5
SOLO               5010
BIDES              B1DE5
SISES              515E5
ASIA               A51A
CALAIS             CA1A15
CELL               CE11
COAL               C0A1
BLOOD              B100D
AIDES              A1DE5
BALBOA             BA1B0A
BESSEL             BE55E1
BLADES             B1ADE5
ABSCISSAE          AB5C155AE
COIFED             C01FED
DOLLIE             D0111E
CLASSED            C1A55ED
SADE               5ADE
CABLE              CAB1E
DOCS               D0C5
SACCO              5ACC0
DICED              D1CED
ELIDES             E11DE5
BLESS              B1E55
CLASSES            C1A55E5
ABSCISSAS          AB5C155A5
BOLLED             B011ED
CODDLE             C0DD1E
FEEDS              FEED5
FILIAL             F111A1
FLEE               F1EE
FLED               F1ED
BABIED             BAB1ED
FLIES              F11E5
ACCEDE             ACCEDE
COLLIDES           C0111DE5
SOCIALS            50C1A15
FILE               F11E
BAAS               BAA5
CELLOS             CE1105
SALES              5A1E5
CODICES            C0D1CE5
BASAL              BA5A1
CALI               CA11
COLLIDED           C0111DED
COIF               C01F
BAAL               BAA1
FLIED              F11ED
BABIES             BAB1E5
SOFA               50FA
DOLBIES            D01B1E5
BALDS              BA1D5
LILACS             111AC5
BIFOCALS           B1F0CA15
CALF               CA1F
EFFACE             EFFACE
BOILED             B011ED
COSIES             C051E5
BOBBLE             B0BB1E
LESS               1E55
SADDLES            5ADD1E5
BABEL              BABE1
COBBLE             C0BB1E
FOALED             F0A1ED
BOOLE              B001E
SOFAS              50FA5
LESA               1E5A
BABES              BABE5
COIL               C011
EFFIE              EFF1E
FACES              FACE5
FILL               F111
DELIA              DE11A
LILIES             1111E5
OILS               0115
SOILS              50115
DAILIES            DA111E5
BILBO              B11B0
SCAFFOLD           5CAFF01D
OFFICIAL           0FF1C1A1
ILIAD              111AD
DECODE             DEC0DE
LOBE               10BE
DELIS              DE115
DAFFODILS          DAFF0D115
SEABED             5EABED

FISCALS            F15CA15
FADE               FADE
CELLED             CE11ED
CLASSICS           C1A551C5
ODESSA             0DE55A
LADE               1ADE
COOLIE             C0011E
SOCIABLES          50C1AB1E5
BASS               BA55
FIBBED             F1BBED
EELS               EE15
DIODE              D10DE
CELLS              CE115
ALICE              A11CE
CELLI              CE111
FOIL               F011
BASE               BA5E
ELSIE              E151E
CELLO              CE110
FOILED             F011ED
BILLFOLDS          B111F01D5
SICES              51CE5
BILLS              B1115
SEEDS              5EED5
LESSEE             1E55EE
ALFALFA            A1FA1FA
COALED             C0A1ED
BIDED              B1DED
ALIBIED            A11B1ED
SABLES             5AB1E5
CECILE             CEC11E
CEDED              CEDED
DADOES             DAD0E5
LIBIDOS            11B1D05
FIEF               F1EF
DABS               DAB5
CEDES              CEDE5
LOCI               10C1
BODICES            B0D1CE5
BLEED              B1EED
COOLED             C001ED
CLIFF              C11FF
CASSIAS            CA551A5
ABSCESS            AB5CE55
BASILICA           BA5111CA
SCALE              5CA1E
BASED              BA5ED
CALICOS            CA11C05
SALAD              5A1AD
FOLLIES            F0111E5
BASEL              BA5E1
ALISSA             A1155A
BILLIES            B1111E5
COLO               C010
ABED               ABED
BASES              BA5E5
FELLS              FE115
ELIAS              E11A5
BOLES              B01E5
CABS               CAB5
ABEL               ABE1
COLE               C01E
DEED               DEED
ISOLDE             1501DE
COLA               C01A
SELFLESS           5E1F1E55
CALLAS             CA11A5
LIFELESS           11FE1E55
ALIASED            A11A5ED
DEIFIED            DE1F1ED
SILOS              51105
EASE               EA5E
SICS               51C5
BILBAO             B11BA0
BADE               BADE
SISSES             5155E5
LOBS               10B5
LOCO               10C0
COOED              C00ED
CALLAO             CA11A0
IDES               1DE5
FIES               F1E5
DEIFIES            DE1F1E5
ALIASES            A11A5E5
BEADS              BEAD5
LIEF               11EF
CODICIL            C0D1C11
LOAFED             10AFED
ELIDE              E11DE
SOBBED             50BBED
LOIS               1015
LIES               11E5
DISCS              D15C5
CLODDED            C10DDED
LOLLED             1011ED
SOLE               501E
AFIELD             AF1E1D
BOBS               B0B5
BILLFOLD           B111F01D
CABOOSES           CAB005E5
LEAF               1EAF
LEAD               1EAD
SADIE              5AD1E
LILLIE             11111E
BOSSED             B055ED
LEAS               1EA5
COILED             C011ED
LOSES              105E5
FLOES              F10E5
BOSSES             B055E5
SEES               5EE5
BALLADS            BA11AD5
SAAB               5AAB
BOIL               B011
OBSESS             0B5E55
DISCLOSE           D15C105E
FOLIOS             F01105
IBLIS              1B115
FACELESS           FACE1E55
SALE               5A1E
BEDSIDES           BED51DE5
DISABLED           D15AB1ED
CODDLES            C0DD1E5
AIDA               A1DA
COLDS              C01D5
IDEA               1DEA
AIDE               A1DE
FLEA               F1EA
BASEBALL           BA5EBA11
DECIDE             DEC1DE
CELIA              CE11A
BOBSLED            B0B51ED
AIDS               A1D5
LOADS              10AD5
CODDLED            C0DD1ED
DOABLE             D0AB1E
CABBED             CABBED
DEFACES            DEFACE5
SASS               5A55
COLED              C01ED
DIDDLE             D1DD1E
IDLE               1D1E
OILED              011ED
FOCI               F0C1
BALLED             BA11ED
DISABLE            D15AB1E
OFFAL              0FFA1
SLOES              510E5
BOILS              B0115
ELISE              E115E
LEIS               1E15
ELISA              E115A
SEEDLESS           5EED1E55
DISCLOSES          D15C105E5
CILIA              C111A
COED               C0ED
OSSIFIED           0551F1ED
FILLS              F1115
EDIFIED            ED1F1ED
SCADS              5CAD5
IDEALS             1DEA15
BELIE              BE11E
CICADA             C1CADA
DISCLOSED          D15C105ED
SALLIED            5A111ED
LADLED             1AD1ED
DOODLED            D00D1ED
LABEL              1ABE1
FALSE              FA15E
COBS               C0B5
DIESELS            D1E5E15
FOLDED             F01DED
DECAL              DECA1
DISEASES           D15EA5E5
SIDLED             51D1ED
BEEFS              BEEF5
SLOBS              510B5
COBB               C0BB
LISA               115A
SLIDED             511DED
OISE               015E
ADDLE              ADD1E
LOADABLE           10ADAB1E
LASSOED            1A550ED
CADS               CAD5
BEDDED             BEDDED
BASIS              BA515
DADA               DADA
ACACIA             ACAC1A
LABIAL             1AB1A1
LADIES             1AD1E5
LODE               10DE
BELLICOSE          BE111C05E
ABBAS              ABBA5
BASIE              BA51E
BLISS              B1155
ALASES             A1A5E5
BASIC              BA51C
ISAAC              15AAC
SLOB               510B
BOLAS              B01A5
SCABIES            5CAB1E5
BAIL               BA11
COCCIS             C0CC15
ABSCESSES          AB5CE55E5
COLLIE             C0111E
OLAF               01AF
LILAC              111AC
FIDEL              F1DE1
DIBBLE             D1BB1E
IDIOCIES           1D10C1E5
ODDBALLS           0DDBA115
CLIFFS             C11FF5
BOISE              B015E
EDDIES             EDD1E5
LADLES             1AD1E5
DIES               D1E5
COLLIES            C0111E5
CALL               CA11
LASSOS             1A5505
CALLED             CA11ED
ABASE              ABA5E
BIASED             B1A5ED
ADOBES             AD0BE5
EFFACES            EFFACE5
ADOLFO             AD01F0
SOCIAL             50C1A1
DOODAD             D00DAD
LEASED             1EA5ED
DELLS              DE115
LICE               11CE
BIDDLE             B1DD1E
ALSACE             A15ACE
BEAD               BEAD
LIBBED             11BBED
LEASES             1EA5E5
COCCI              C0CC1
FLEES              F1EE5
DELLA              DE11A
BLISSED            B1155ED
FOCAL              F0CA1
DICE               D1CE
FLOSSIE            F10551E
SOLID              5011D
DAFFODIL           DAFF0D11
ABODED             AB0DED
FIBS               F1B5
BOODLES            B00D1E5
BLOODIES           B100D1E5
FEELS              FEE15
IDOL               1D01
BESIDES            BE51DE5
LIDDED             11DDED
SALLIE             5A111E
OFFICES            0FF1CE5
ABODES             AB0DE5
EASIES             EA51E5
ISLES              151E5
FAECES             FAECE5
BASELESS           BA5E1E55
LIFEBLOOD          11FEB100D
LACE               1ACE
OBOE               0B0E
BELLE              BE11E
IBICES             1B1CE5
BELLA              BE11A
SIDLE              51D1E
LADDIE             1ADD1E
ASSES              A55E5
SOLES              501E5
FOLDS              F01D5
BESS               BE55
SODDED             50DDED
BELLS              BE115
FOOSBALL           F005BA11
FEES               FEE5
SILAS              511A5
BAOBAB             BA0BAB
CALICO             CA11C0
SOLIDIFIED         5011D1F1ED
DEBBIE             DEBB1E
IDOLS              1D015
BALLAD             BA11AD
EBBED              EBBED
ASOCIAL            A50C1A1
BIBLES             B1B1E5
EDIFICE            ED1F1CE
COCOAS             C0C0A5
CABLED             CAB1ED
OLLIE              0111E
SALSA              5A15A
SCOLDS             5C01D5
BOSS               B055
FLOOD              F100D
BASICS             BA51C5
COEDS              C0ED5
ABBESS             ABBE55
OLEO               01E0
BOSE               B05E
DEBS               DEB5
SLABS              51AB5
FALLOFFS           FA110FF5
EDIBLE             ED1B1E
FLEECE             F1EECE
ADDS               ADD5
BIFOCAL            B1F0CA1
COIFFED            C01FFED
SOLED              501ED
ADELA              ADE1A
FAILED             FA11ED
BEEBE              BEEBE
ADELE              ADE1E
CASELOADS          CA5E10AD5
CLAD               C1AD
FOOLED             F001ED
LACES              1ACE5
BAILIFFS           BA111FF5
FOOL               F001
FIFE               F1FE
BACALL             BACA11
BIBLICAL           B1B11CA1
BELL               BE11
CODIFIES           C0D1F1E5
BIDS               B1D5
BELA               BE1A
OFFS               0FF5
FIASCOS            F1A5C05
SOLOS              50105
ACADIA             ACAD1A
ALBEE              A1BEE
BOAS               B0A5
BIBS               B1B5
FELICE             FE11CE
LIDS               11D5
CODIFIED           C0D1F1ED
ODDBALL            0DDBA11
LEES               1EE5
ISSAC              155AC
FILLED             F111ED
FIELDS             F1E1D5
DIDDLED            D1DD1ED
SEABEDS            5EABED5
DOFF               D0FF
COALESCE           C0A1E5CE
CABAL              CABA1
OLDFIELD           01DF1E1D
LESSEES            1E55EE5
EBBS               EBB5
IDLES              1D1E5
IBISES             1B15E5
DECADES            DECADE5
FACED              FACED
FADS               FAD5
FLEAS              F1EA5
BLADE              B1ADE
LIAISE             11A15E
COLAS              C01A5
FOOD               F00D
CADILLAC           CAD111AC
FLAILS             F1A115
LIBELLED           11BE11ED
DOFFED             D0FFED
DIDDLES            D1DD1E5
LOBBIED            10BB1ED
BOBBI              B0BB1
SILICOSIS          5111C0515
SAILS              5A115
BOOB               B00B
DEICE              DE1CE
COLS               C015
CLOSES             C105E5
SABLED             5AB1ED
BEEF               BEEF
CALICOES           CA11C0E5
BABBLED            BABB1ED
ICES               1CE5
BEES               BEE5
FIDDLE             F1DD1E
CLOSED             C105ED
LIABLE             11AB1E
SOLIDIFIES         5011D1F1E5
FLOSSES            F1055E5
SAFES              5AFE5
LEIF               1E1F
BABBLES            BABB1E5
LASSES             1A55E5
OFFICE             0FF1CE
EASELS             EA5E15
LOOSED             1005ED
SEAFOOD            5EAF00D
EIFFEL             E1FFE1
IDEAS              1DEA5
ABIDE              AB1DE
SODAS              50DA5
DILLIES            D1111E5
IDEAL              1DEA1
BIBLE              B1B1E
DODOS              D0D05
SCOLDED            5C01DED
FLAILED            F1A11ED
LOADED             10ADED
ALIBIS             A11B15
FALLS              FA115
DISBELIEF          D15BE11EF
LOAD               10AD
CASE               CA5E
OBESE              0BE5E
DOLLIES            D0111E5
ADOBE              AD0BE
DECCA              DECCA
OFFED              0FFED
FLOODED            F100DED
SILLS              51115
BOODLE             B00D1E
DIED               D1ED
SECS               5EC5
DOES               D0E5
LEEDS              1EED5
IACCOCA            1ACC0CA
DOLED              D01ED
FLOSS              F1055
BLEEDS             B1EED5
DEFILE             DEF11E
SAFE               5AFE
BALL               BA11
BALI               BA11
SALSAS             5A15A5
CALLIE             CA111E
BALE               BA1E
BALD               BA1D
SCOLD              5C01D
FALLACIES          FA11AC1E5
FACADES            FACADE5
SCALED             5CA1ED
FIELD              F1E1D
DABBED             DABBED
FECES              FECE5
ESSIE              E551E
BOLDS              B01D5
FAIL               FA11
BESSIE             BE551E
BILLIE             B1111E
LEOLA              1E01A
LIAISES            11A15E5
BILE               B11E
COBBED             C0BBED
DECIDES            DEC1DE5
DOLLED             D011ED
CABOOSE            CAB005E
BEFALLS            BEFA115
BILL               B111
LEADS              1EAD5
SELF               5E1F
DECIDED            DEC1DED
FIASCO             F1A5C0
COLIC              C011C
SIDE               51DE
DAISES             DA15E5
BOOBIES            B00B1E5
BOLA               B01A
BELIEF             BE11EF
OLDIES             01D1E5
BELIED             BE11ED
FEEL               FEE1
OILFIELDS          011F1E1D5
ALCOA              A1C0A
SCAD               5CAD
BAILIFF            BA111FF
DOSE               D05E
BELIES             BE11E5
BASIL              BA511
DISEASED           D15EA5ED
SLICE              511CE
ASOCIALS           A50C1A15
BOLE               B01E
LEAFLESS           1EAF1E55
IDLED              1D1ED
LOLA               101A
LIBELS             11BE15
SALEABLE           5A1EAB1E
ODELL              0DE11
LEAFED             1EAFED
LOLL               1011
LEDA               1EDA
DEFOE              DEF0E
OASIS              0A515
DICES              D1CE5
SILICA             5111CA
AFFABLE            AFFAB1E
LILIA              1111A
BLOODED            B100DED
FELLED             FE11ED
LESSIE             1E551E
LIDIA              11D1A
SISSIES            51551E5
COLOSSAL           C01055A1
ODDS               0DD5
ASIDES             A51DE5
AISLED             A151ED
DECALS             DECA15
ALIAS              A11A5
DOILIES            D0111E5
SELASSIE           5E1A551E
FIFES              F1FE5
FACADE             FACADE
AISLES             A151E5
CLODS              C10D5
CABLES             CAB1E5
DAISIES            DA151E5
FISCAL             F15CA1
DADO               DAD0
OFFSIDE            0FF51DE
FOBS               F0B5
OSLO               0510
EDDIED             EDD1ED
ABASED             ABA5ED
SIDES              51DE5
ACCESS             ACCE55
FELL               FE11
SEALS              5EA15
ABASES             ABA5E5
DADS               DAD5
SALADO             5A1AD0
COILS              C0115
LACED              1ACED
LOSSES             1055E5
ASSAILED           A55A11ED
LADS               1AD5
DEAL               DEA1
DOLL               D011
FOOLS              F0015
LIBEL              11BE1
DEAF               DEAF
DOLE               D01E
FICES              F1CE5
LISLE              1151E
BOBBED             B0BBED
FAISAL             FA15A1
LABELLED           1ABE11ED
OBSESSED           0B5E55ED
FIASCOES           F1A5C0E5
DOODLES            D00D1E5
COLLIED            C0111ED
SALADS             5A1AD5
FEEBLE             FEEB1E
CLEFS              C1EF5
FECAL              FECA1
CLASSLESS          C1A551E55
SCABBED            5CABBED
DEBASE             DEBA5E
SODS               50D5
CLASSIC            C1A551C
FIELDED            F1E1DED
FOILS              F0115
LILLE              1111E
SCOFF              5C0FF
SECEDE             5ECEDE
COALESCES          C0A1E5CE5
COOLIES            C0011E5
SADDLED            5ADD1ED
SODA               50DA
DIALLED            D1A11ED
SEASIDES           5EA51DE5
FELECIA            FE1EC1A
BOBBLED            B0BB1ED
BASILICAS          BA5111CA5
BOLD               B01D
DIBBLED            D1BB1ED
ALBA               A1BA
FABLE              FAB1E
ASCELLA            A5CE11A
BLABS              B1AB5
BALSA              BA15A
BOLL               B011
SLED               51ED
DIBBLES            D1BB1E5
CECELIA            CECE11A
SLABBED            51ABBED
BIAS               B1A5
BOBBLES            B0BB1E5
DIODES             D10DE5
DECIBEL            DEC1BE1
ALBS               A1B5
DIABOLIC           D1AB011C
DISSES             D155E5
LOCALED            10CA1ED
BAAED              BAAED
ICICLE             1C1C1E
CALEB              CA1EB
COLLIDE            C0111DE
ALES               A1E5
DISSED             D155ED
DEBACLE            DEBAC1E
COALS              C0A15
CABALS             CABA15
FLEECES            F1EECE5
ALISA              A115A
LOCALLED           10CA11ED
EDIBLES            ED1B1E5
LOCALES            10CA1E5
ALEC               A1EC
SOLACES            501ACE5
FLACCID            F1ACC1D
ADOLF              AD01F
BLOCS              B10C5
LASSIES            1A551E5
DISCOS             D15C05
BLABBED            B1ABBED
ASIDE              A51DE
LABS               1AB5
DALLIED            DA111ED
BIASSED            B1A55ED
DOFFS              D0FF5
CODICILS           C0D1C115
CASSIA             CA551A
FLEECED            F1EECED
LASSOES            1A550E5
CASSIE             CA551E
FOES               F0E5
COBBLED            C0BB1ED
ADDED              ADDED
LILA               111A
BAILED             BA11ED
BEDE               BEDE
LEADED             1EADED
BEDS               BED5
DELIBES            DE11BE5
DEBASES            DEBA5E5
ALLIED             A111ED
FALLIBLE           FA111B1E
BOBBIE             B0BB1E
FOSSIL             F05511
LADLE              1AD1E
ALOOF              A100F
BASSOS             BA5505
DIOCESES           D10CE5E5
CECIL              CEC11
BODICE             B0D1CE
SLIDES             511DE5
DECIBELS           DEC1BE15
SEASIDE            5EA51DE
CABBIE             CABB1E
SEALED             5EA1ED
DISABLES           D15AB1E5
ACIDIFIES          AC1D1F1E5
BEADLE             BEAD1E
DISEASE            D15EA5E
DEALS              DEA15
OAFS               0AF5
SACS               5AC5
BEFELL             BEFE11
DALLIES            DA111E5
LOCALS             10CA15
OFELIA             0FE11A
BIDDIES            B1DD1E5
ELBE               E1BE
ABBASID            ABBA51D
ELBA               E1BA
SOLACE             501ACE
CLASSIFIES         C1A551F1E5
BOOED              B00ED
DIESEL             D1E5E1
FALLOFF            FA110FF
SCOFFS             5C0FF5
ISLE               151E
COCOA              C0C0A
BEADED             BEADED
LAID               1A1D
FILED              F11ED
SECEDED            5ECEDED
BIASES             B1A5E5
SCALDS             5CA1D5
DILL               D111
FIDDLES            F1DD1E5
FELICIA            FE11C1A
ELOISE             E1015E
COOLS              C0015
BABBLE             BABB1E
CABOODLE           CAB00D1E
SCALD              5CA1D
SCOLIOSIS          5C0110515
BLED               B1ED
LEILA              1E11A
ALAS               A1A5
FIDDLED            F1DD1ED
SOSA               505A
DOCILE             D0C11E
CLIO               C110
CELEBES            CE1EBE5
SILL               5111
BELIEFS            BE11EF5
DISS               D155
SILO               5110
DOSSES             D055E5
ISIS               1515
LOCAL              10CA1
EDDA               EDDA
BALED              BA1ED
FOODS              F00D5
SALLIES            5A111E5
SLOE               510E
OFFSIDES           0FF51DE5
EASEL              EA5E1
CLOSE              C105E
EASED              EA5ED
DEEDED             DEEDED
BALES              BA1E5
CEDILLA            CED111A
FADES              FADE5
FAILS              FA115
FABLES             FAB1E5
BOBSLEDS           B0B51ED5
BODED              B0DED
ICICLES            1C1C1E5
BOLLS              B0115
BALSAS             BA15A5
BOBBIES            B0BB1E5
CASCADE            CA5CADE
FABLED             FAB1ED
ASSISI             A55151
FADED              FADED
AILED              A11ED
OFFLOAD            0FF10AD
SLAB               51AB
CACAO              CACA0
BODES              B0DE5
DIALED             D1A1ED
OBSESSES           0B5E55E5
DABBLE             DABB1E
DADOS              DAD05
BLOODIED           B100D1ED
BELLED             BE11ED
SALAS              5A1A5
BOOS               B005
ABLE               AB1E
DABBLED            DABB1ED
BELLES             BE11E5
BEDSIDE            BED51DE
DABBLES            DABB1E5
FOBBED             F0BBED
BIDE               B1DE
DIESELED           D1E5E1ED
FACILE             FAC11E
DALE               DA1E
COFFEE             C0FFEE
ABACI              ABAC1
LOAFS              10AF5
OASES              0A5E5
ALIBI              A11B1
LOCALE             10CA1E
CADDIED            CADD1ED
FLOE               F10E
ALICIA             A11C1A
DALI               DA11
LADED              1ADED
ASSAD              A55AD
BAFFLE             BAFF1E
FOLLICLE           F0111C1E
DISC               D15C
ODIS               0D15
ODES               0DE5
LADES              1ADE5
FACE               FACE
SOLOED             5010ED
COLD               C01D
CADDIES            CADD1E5
BLOODS             B100D5
CEDE               CEDE
DODOES             D0D0E5
ABIDED             AB1DED
DIOCESE            D10CE5E
SCALES             5CA1E5
ADDIE              ADD1E
BACILLI            BAC1111
ALSO               A150
LABIALS            1AB1A15
ABIDES             AB1DE5
DEAD               DEAD
FOLIO              F0110
OBOES              0B0E5
LIAISED            11A15ED
DEFACE             DEFACE
DEFILES            DEF11E5
ELIDED             E11DED
BALLS              BA115
BLISSES            B1155E5
LABIA              1AB1A
DELI               DE11
SIDLES             51D1E5
FALSIFIES          FA151F1E5
DELL               DE11
OSCEOLA            05CE01A
DALES              DA1E5
FIEFS              F1EF5
CLASS              C1A55
SADES              5ADE5
DEFILED            DEF11ED
COFFEES            C0FFEE5
ALLIES             A111E5
ACACIAS            ACAC1A5
FALSIFIED          FA151F1ED
DECADE             DECADE
DEBASED            DEBA5ED
SELL               5E11
DECAF              DECAF
ABSCISSA           AB5C155A
CALLABLE           CA11AB1E
FOLLICLES          F0111C1E5
SASSED             5A55ED
LIBELED            11BE1ED
BALDED             BA1DED
SASSES             5A55E5
SLEDS              51ED5
ICED               1CED

Hexspeak and generator

EDIT 2011-04-021: While browsing my old blogposts, I found the code here can be greatly improved. Here it is:

def words():
    with open('/usr/share/dict/words', 'r') as f:
        return (x.strip().upper() for x in f.readlines())

MAPPING = {'A':'A', 'B':'B', 'C':'C', 'D':'D',
           'E':'E', 'F':'F', 'O':'0', 'S':'5', 'I':'1'}

def main():
    is_hexword = lambda word: all(ch in MAPPING for ch in word)
    for word in filter(is_hexword, words()):
        print word, "\t", ''.join(MAPPING.get(ch, ch) for ch in word)

if __name__ == '__main__':

So, it’s a relatively slow day at work, and I’ve been “stumbling upon” on Wikipedia when I found this:


It’s pretty interesting, because I remember OS161 from my operating system course where they use 0xDEADBEEF as a value for uninitialized pointers. So I decided to write a small Python program that finds me all the “Hexspeak” words from a regular English dictionary.

Beginning by finding a plain text English dictionary. I know Linux has a file ‘words’ in the file system somewhere. A little search gives me its location: /usr/share/dict/words

Now onto Python coding:

Define a character-to-hex map:

HEXSPEAK_DICT={'A':'A', 'B':'B', 'C':'C', 'D':'D', 'E':'E', 'F':'F', 'O':'0', 'L':'1', 'S':'5', 'I':'1', }

Define a method to open the dictionary and return a list of words:

DICT = '/usr/share/dictdef words(file=DICT):
    f = open(file, 'r')
    retval = f.readlines()
    retval = [ x.strip().upper() for x in retval ]
    return retval

Define a method to print out the collection of hexspeaks

def print_dict(dict):
    for key in dict.keys():
        print "%-20s\t%s"%(key, dict[key])

Finally, the main method

WORDS = words
def main():
    hexspeak_list = {}
    for word in WORDS():
        hexspeak = []
            for char in word:
                if char in HEXSPEAK_DICT.keys():
                    raise Exception
            hexspeak_list[word] = "".join(hexspeak)


The program itself is pretty clear. We go through every character in every word in the dictionary. If the character is not in a permitted Hexspeak character, we through out the word. Otherwise, we take the character and translate it into a hexspeak character if necessary. Finally we print out the whole thing.

Running it, it gives me a list of hexspeak words. Everything is cool.

Now, the idea of generator has been around for a while. If you’re operating on a list, instead of loading the list into memory at once, you can use a generator and return one piece at a time, so it can save some resources. Granted, I’ve never used generators before, so I decided to experiement using a generator.

Here’s the code. Everytime xwords() is called, it returns the next processed value in the list.

def xwords(file=DICT):
    f = open(file, 'r')
    retval = f.readlines()

    for rv in retval:
        yield rv.strip().upper()

Now we need to modify WORDS to make it point to xwords

WORDS = xwords

Running it, it gives the same result. So my experiment with generator succeeded! Hooray!

However, a little profiling on the program contradicts the intuition that using a generator is faster. I used Python’s timeit module for profiling:

python -m timeit -n 3 'import hexspeak; hexspeak.main()'

Using generator:

3 loops, best of 3: 565 msec per loop

Using list:

3 loops, best of 3: 549 msec per loop

Hmmm, so not only using a generator doesn’t save me any time, it actually got beaten by a tad bit by the plain ol’ list implementation…I’m sure I’m missing some points here. A good topic for a blog post for another day.

Here’s a list of Hexspeak words