import random
class Markov(object):
def __init__(self, samples, order, minLength):
self.order = order
self.minLength = minLength
self.chains = {}
self.used = []
self.samples = [i.strip().upper() for i in samples if len(i) > order]
for word in self.samples:
for letter in xrange(len(word)-order):
token = word[letter:letter+order]
entries = self.chains.setdefault(token, list())
entries.append(word[letter + order])
def next(self):
s = "";
while True:
n = random.choice(self.samples)
i = random.randint(0, len(n) - self.order)
s = n[i:i+self.order]
while len(s) < len(n):
i = random.randint(0, len(s) - self.order)
token = s[i:i+self.order]
if token not in self.chains:
break
s += random.choice(self.chains[token])
s = s[0] + s[1:].lower()
if not (s in self.samples or s in self.used or len(s) < self.minLength):
break
self.used.append(s);
return s;
def reset(self):
self.used.Clear()
You can seed it with any data you like to generate any sort of name. Eg:
starnames = """
Achernar Alpha Eridani \
Achird Eta Cassiopeiae \
Acrab Beta Scorpii \
Acrux Alpha Crucis \
Acubens Alpha Cancri \
Adhafera Zeta Leonis \
Adhara Epsilon Canis Majoris \
Ain Epsilon Tauri \
Aladfar Eta Lyrae \
Alamak Gamma Andromedae \
Alathfar Mu Lyrae \
Alaraph Beta Virginis \
Albaldah Pi Sagittarii \
""".split(" ")
m = Markov(starnames, 2, 6)
for i in xrange(10):
print m.next()
Gives this output:
Siolphh
Hafere
Ammaam
Ammaka
Ittatartar
Chieri
Scooor
Araineaa
Feriisda
Achuih