Generate Random Pronouceable Words

Ho haï, blog, long time no see! :)

I was checking stuff on various URL shorteners and noticed is.gd has one interesting feature: you can generate short URLs that are "pronounceable" (no "vgfhgt"). This is a great little touch: a random but pronounceable word will be more memorable and the probability for typos is reduced, which makes it a killer feature for random generated passwords for example.

Generating pronounceable random words isn't difficult :

  • start by a vowel or a consonant
  • alternate and add letters till proper word length

Simple, but this generates words that are too simple maybe: 'abuco', 'misolo', 'xulanipo', etc… Natural words also use a few consecutive consonant combinations as well as vowel combos ('cheepo', 'bergam', …)

I ended up with this simple piece of code that gives more natural words:

<?php
/**
 * Generate random pronounceable words
 *
 * @param int $length Word length
 * @return string Random word
 */
function random_pronounceable_word( $length = 6 ) {
	
	// consonant sounds
	$cons = array(
		// single consonants. Beware of Q, it's often awkward in words
		'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
		'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'z',
		// possible combinations excluding those which cannot start a word
		'pt', 'gl', 'gr', 'ch', 'ph', 'ps', 'sh', 'st', 'th', 'wh', 
	);
	
	// consonant combinations that cannot start a word
	$cons_cant_start = array( 
		'ck', 'cm',
		'dr', 'ds',
		'ft',
		'gh', 'gn',
		'kr', 'ks',
		'ls', 'lt', 'lr',
		'mp', 'mt', 'ms',
		'ng', 'ns',
		'rd', 'rg', 'rs', 'rt',
		'ss',
		'ts', 'tch', 
	);
	
	// wovels
	$vows = array(
		// single vowels
		'a', 'e', 'i', 'o', 'u', 'y', 
		// vowel combinations your language allows
		'ee', 'oa', 'oo', 
	);
	
	// start by vowel or consonant ?
	$current = ( mt_rand( 0, 1 ) == '0' ? 'cons' : 'vows' );
	
	$word = '';
		
	while( strlen( $word ) < $length ) {
	
		// After first letter, use all consonant combos
		if( strlen( $word ) == 2 ) 
			$cons = array_merge( $cons, $cons_cant_start );

		 // random sign from either $cons or $vows
		$rnd = ${$current}[ mt_rand( 0, count( ${$current} ) -1 ) ];
		
		// check if random sign fits in word length
		if( strlen( $word . $rnd ) <= $length ) {
			$word .= $rnd;
			// alternate sounds
			$current = ( $current == 'cons' ? 'vows' : 'cons' );
		}
	}
	
	return $word;
}

?>

(bleh, just noticed the fuckingfancy curled quoted are back in code blocks. pastebin for cut'n'paste code)

Play with the demo: random pronounceable words.

Nothing elaborated enough to help you create an alien language for your next sci-fi movie, but I'm rather pleased with the random words it creates. It's also easy to implement this in another language: modify the group of consecutive vowels and consonants to match what exists in your language.

4 comments

  1. Hajo

    Thanks! For some internal project I ported your code to bash:

    #!/bin/bash
    
    function rpw {
    
            cons=(b c d f g h j k l m n p r s t v w x z pt gl gr ch ph ps sh st th wh)
            conscs=(ck cm dr ds ft gh gn kr ks ls lt lr mp mt ms ng ns rd rg rs rt ss ts tch)
            vows=(a e i o u y ee oa oo)
    
            len=$((($1+0 == 0) ? 6 : $1+0))
            alt=$RANDOM
            word=
    
            while [ ${#word} -lt $len ]; do
    
                    if [ $(($alt%2)) -eq 0 ]; then
                            rc=${cons[(($RANDOM%${#cons[*]}))]}
                    else
                            rc=${vows[(($RANDOM%${#vows[*]}))]}
                    fi
    
                    if [ $((${#word}+${#rc})) -gt $len ]; then continue; fi
    
                    word=$word$rc
    
                    ((alt++))
    
                    if [ ${#word} -eq 1 ]; then
                            cons=(${cons[@]} ${conscs[@]})
                    fi
    
            done
    
            echo $word
    }
    
    rpw
    
    rpw 4
  2. Ozh

    Hajo » nice :)

  3. Hajo

    Oups, an error, you have to replace lines 27-29 with this:

    if [ ${#conscs[*]} -gt 0 ]; then
                            cons=(${cons[@]} ${conscs[@]})
                            conscs=()
                    fi
  4. @emersonbroga

    I created a Swift Version…

    https://gist.github.com/emersonbroga/f84c7490d1813902a61b

    thanks.

Comments are closed.