Log in

No account? Create an account
Naming twins in Python & Perl - brad's life [entries|archive|friends|userinfo]
Brad Fitzpatrick

[ website | bradfitz.com ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Naming twins in Python & Perl [Jan. 6th, 2008|02:16 pm]
Brad Fitzpatrick
[Tags|, , , ]

Last night at Beau's party, one of Beau's guests mentioned he's expecting twins shortly, which is why is wife wasn't at the party.

I drunkenly suggested he name his kids two names that were anagrams of each other. I then wandered off downstairs to find such suitable names.

Because I'm supposed to be be working in Python these days, not Perl, I gathered what little Python knowledge I had and wrote out:

by_anagram = {}

names_file = open("dist.male.first")
for line in names_file:
    # lines in file look like:
    # WILLIAM        2.451 14.812      5
    # we want just the first field.
    name = (line.split())[0]
    letters = [letter for letter in name]
    sorted_name = "".join(letters)
    if not sorted_name in by_anagram:
        by_anagram[sorted_name] = []

for sorted_name in by_anagram:
    if len(by_anagram[sorted_name]) < 2:

    print by_anagram[sorted_name]
Not so happy with it, but it worked, and I printed out the results and brought them up to the guy:
['TROY', 'TORY']
['CLAY', 'LACY']
['DEAN', 'DANE']
['COLE', 'CLEO']
['LEON', 'NOEL', 'OLEN']
['NEAL', 'LANE']
['BERT', 'BRET']
['OLIN', 'LINO']
['DION', 'DINO']
['DANA', 'ADAN']
Just now, I was wondering the equivalent in Perl, and wrote:

use strict;
open (my $fh, "dist.male.first") or die;
my %by_anagram;
while (<$fh>) {
    my $name = $_;
    my $sorted_name = join('', sort split //, $name);
    push @{$by_anagram{$sorted_name}}, $name;

foreach my $sn (grep { @{$by_anagram{$_}} > 1 } keys %by_anagram) {
    print "@{$by_anagram{$sn}}\n";
In particular, I like about Python that errors-are-exceptions is the norm. But I like that regexps are built into Perl. (also hate Python's general hating on functional programming, unrelated to this post) I'm sure my Python could be way shorter, too. Anybody want to post either their short Python version, or their more-idiomatic Python version?

Also interesting: (fastest of a 3 consecutive runs each)
sammy$ time ./ananames.pl > /dev/null

real	0m0.026s
user	0m0.024s
sys	0m0.004s

sammy$ time ./ananames.py > /dev/null

real	0m0.043s
user	0m0.036s
sys	0m0.008s

[User Picture]From: nothings
2008-01-07 04:29 am (UTC)
For what little it's worth:

#define STB_DEFINE
#include "stb.h"     // http://nothings.org/stb.h

stb_sdict *names;

int main(int argc, char **argv)
   int i,j;
   char **lines, *y;
   names = stb_sdict_new(1);
   lines = stb_stringfile("/sean/writing/tools/male.txt", NULL);
   for (; *lines; ++lines) {
      char **z = stb_tokens(*lines, " ", NULL), *p = strdup(z[0]), **s;
      qsort(z[0], strlen(z[0]), 1, stb_charcmp);
      s = stb_sdict_get(names, z[0]);
      stb_arr_push(s, p);
      stb_sdict_set(names, z[0], s);
   stb_sdict_for(names, i, y, lines) {
      if (stb_arr_len(lines) > 1) {
         printf("[ ");
         for (j=0; j < stb_arr_len(lines); ++j) {
            printf("'%s' ", lines[j]);
   return 0;

Of course that leaks all memory, and I don't have perl or python installed to do a performance comparison anyway.
(Reply) (Thread)