Random Name Generator

Given an array of example names, use a Markov-chain-like approach to generating new thematically similar names

by Tonio Loewald

CSS

p {
  padding: 0;
  margin: 0;
  text-transform: capitalize;
}

JavaScript

const seed = [
	'Aragorn',
  'Elrond',
  'Eowyn',
  'Faramir',
  'Theoden',
  'Saruman',
  'Gandalf',
  'Legolas',
  'Arwen',
  'Gimli',
  'Samwise',
  'Frodo',
  'Boromir',
  'Denethor',
  'Galadriel',
  'Celeborn',
  'Meriadoc',
  'Peregrin',
  'Sauron',
  'Garstang',
  'Radagast',
  'Gollum',
  'Shelob',
  'Isildur',
  'Elendil',
  'Eldarion',
  'Anarion',
  'Grima',
  'Glorfindel',
  'Beregond',
  'Fredegar',
  'Smaug',
  'Tinuviel',
  'Luthien',
  'Feanor',
  'Beren',
  'Turin',
  'Maedhros',
  'Hurin',
  'Fingolfin',
  'Finwe',
  'Maglor'
]

function pick(array) {
  return array[Math.floor(Math.random() * array.length)];
}

class NameGenerator {
// data is a map from character-pairs to observed successors,
// consider the examples "how", "now", "brown", "cow"
// the pair "ow" would have the following successors
// [undefined, undefined, "n", undefined] (undefined -> end of word)

  constructor(examples) {
    const data = {'': []};
    examples.
    map(s => s.toLowerCase()).
    forEach(example => {
      let pair = '';
      data[pair].push(example[0]);

      for(let i = 0; i < example.length; i++) {
        pair = pair.substr(-1) + example[i];
        if (! data[pair]) data[pair] = [];
        if (data[pair].indexOf(example[i+1]) === -1) data[pair].push(example[i + 1]);
      }
    });

    console.log(data);
    this.data = data;
  }

  generate() {
    let s = pick(this.data['']);
    let next = pick(this.data[s]);
    while(next){
      s += next;
      next = pick(this.data[s.substr(-2)]);
    }
    return s;
  }
}

const generator = new NameGenerator(seed);

for(let i = 0; i < 1000; i++) {
	p = document.createElement('p');
  p.textContent = generator.generate();
  document.body.appendChild(p);
}