The essence of perl is indeed that of string manipulation - and no tool better than that of the powerful regular expression engine. When understood correctly, this can make quick work of all your string tasks.
At the core of this are four lines. Just four - two of them
are rather boring.
- Select three separate strings - two from elements, one from endings. Place an 'X' between these as a place holder.
- Replace two non-vowels separated by an 'X' with the
two non-vowels separated by an 'a'.
- Replace a letter followed by an 'X' followed by the same letter again with only one instance of that letter.
- Replace all 'X' with nothing (remove all 'X's)
The 'qw' operator in perl is for quote words. This
changes a list of words into a list of quoted words removing
the need for having quotes around them or commas between the
elements. It is understood that words separated by white space are being changed into a list. This is being assigned to an array called 'elements'. The '@' in front of the array says that this is indeed an array (think '@' which kind of looks like an 'a' meaning array - in perl, another name for list). The same is done for the list of words 'ends'.
The scalar ('$' looks like an 's') variable 'name' is being created which is composed of three parts. A scalar variable
is something that holds one something. The something
is most often a string (of letters), or a number - though there
are a few other values that are scalars that are more difficult to
The $name value is built of a member of the @elements list. To use access this list, the [ and ] designates which number value from the list is to be selected ('abig' is in spot 0, 'ad' is spot '1', and so on). The '$' at the start of '$elements' means that we are expecting a scalar from this value (it is possible to stuff lists into lists...). 'rand' is then called with the @elements array as a parameter. When used in a place where a number is expected, an array has the value of the number of elements in the array. When 'rand' is called with a number as a parameter, it returns a real pseudo-random number between 0 and the parameter. This number value is then used as the index into the list again as an integer (rounded down).
The '.' operator is that of string concatenation. People who have touched upon visual basic will recognize this as the & while java types will be more familiar with '+'. Here, an 'X' is placed between elements of the string to designate the boundaries between them (which are tested later).
The heart and soul of this program is three lines. Two really,
the third is just cleanup.
The 's///' operator in perl is one that converts what is between
the first and second '/' with what is between the second and
third '/' with any options following it. This invokes the
regular expression engine on the first part and our fun begins.
The [ and ] within a regular expression designate a
character class - a set of characters. Here that set is all
the characters except the vowels (aeiouy). This is done
with the '^' meaning 'not'. Around these character classes are
parentheses which stores the values matched into memory - the
first item in $1, the second in $2.
The match of "lXr" becomes "lar" - the 'l' is in $1, the 'r' is in
$2 and the pattern
matches it. This expression runs through all the string
(not just the first match - the 'g' is for 'global') and replaces
it every time it is found.
The second match is similar to the first, except that now any
character can be matched. In regular expressions, the '.'
matches any character. Once again the parentheses store the
value matched. In the regular expression a '$' means the end
of line and to say "that first thing" one has to use a '\' which
is a special character in programing worlds to say what follows
next is special. The '\1' means that first thing again. Here,
we match "letter X same letter" and replace it with just that
letter once. Thus 'aXa' is matched, 'a' is in $1, and the string
is replaced by just 'a'.
The last thing that needs to be done is the simplest - remove all 'X' from the string, and then print it.
@elements = qw(
abig ad adri agard agath aid albert alethe and alexi alfred alm
alt althe alv alvir amand ameli anc andre angel ann anthe antoni
aren arb arci aric arili arit arlen arlott aronic arri arth ashli
astasi athsheb atild atri audre august aureli auror avel averli
bell be bern berth beth beul bonni bridgi brunild carinn cat cecili
chlo clar claudi col colen consuel corneli cor cosett cyndi dan
dari darl debor del dolor dulci dorothe dor edn elaid ell ev fann
fausti feli ferd fifi flor franci fred genev georgi gild gin giov
giuli glori gret griseld gunill gwend helg hephzib henri herth
honori horati huld hermi hest is jessic jeann jemim jo kristi laur
le len lind lis livi lol lon lor lorn louis luci magd mari mir mil
mind mon monic nad ness nicol non nor norm ori priscill penel polli
raciel rebecc regin rhod robert ros sand shirl sib son stell steph
sus sylvi tar tess tiff trici ver vinni viv wilm yol);
@ends = qw(a abel alison amy chen ie ietty icia ietta ina);
$elements[rand @elements] . 'X' .
$elements[rand @elements] . 'X' .
$name =~ s/([^aeiouy])X([^aeiouy])/$1a$2/g;
$name =~ s/(.)X\1/$1/g;
$name =~ s/X//g;
print ucfirst($name), "\n";