#!/usr/bin/python
#you'll need my library pype; http://arvindn.livejournal.com/68137.html; you can get it with:
# $ svn checkout svn://randomwalker.info/pype/pype.py
#do this first
# $ wget -qO- http://www.census.gov/genealogy/names/dist.male.first | cut -d \ -f 1 > firstnames
# $ wget -qO- http://www.census.gov/genealogy/names/dist.female.first | cut -d \ -f 1 >> firstnames
# $ wget -qO- http://www.census.gov/genealogy/names/dist.all.last | cut -d \ -f 1 > lastnames
#finally, copy the list of usernames from the csv into "usernames.in", 1 per line
import os
from pype import *
#read in the list of first names
firstnames = os.popen("echo; cat firstnames") | pStrip | pLower | pSet
#this is trickier: we don't want rare (index > 5000) lastnames that are too short;
#because it leads to spurious matches
lastnames = os.popen("echo; head -5000 lastnames; tail -n +5000 lastnames | grep .....") | pStrip | pLower | pSet
#dictionary words. but not proper nouns.
words = os.popen("grep -v '[A-X]' /usr/share/dict/words") | pStrip | pSet
#check if a pair of words looks like a name
def validName(left, right):
if len(left) in [1,2]: return False #length 0 is ok. length >=3 is ok.
if len(right) in [1,2]: return False
return (left in firstnames and right in lastnames) or \
(left in lastnames and right in firstnames)
#check if a username looks like a first/last name pair
def matchName(username):
for i in xrange(len(username)):
#cut the string at each possible index and check
left, right = username[:i], username[i:]
#we don't allow dictionary words, since that leads to spurious matches
#compromise: but if only one of the names is a dictionary word it's ok
#it's surprising how many first & last names are in fact english words
if validName(left, right) and (left not in words or right not in words):
return left, right
titleCase = lambda word: word[0].upper() + word[1:].lower() if word else ''
#read usernames from usernames.in, but strip non-alphabetical characters
#test each username and write found names to realnames.out
os.popen("sed 's/[^a-zA-Z]//g' usernames.in") | pStrip | pLower | Map(matchName) | Filter(lambda x:x) | Map(lambda name:" ".join(titleCase(w) for w in name)) | pStrip | pWrite("realnames.out")