Posted in Development on Friday, Friday, June 13, 2008 by Anthony Burns
My memory sucks. I'm like a knackered old 286 with 32MB of memory; it's all stored on the hard drive somewhere, but getting it into RAM and then to the CPU is a bit of a challenge. So after discovering memory tricks in Derren Brown's book Tricks of the Mind, I set about learning as much as I could on the subject and began putting it all to work.
The premise behind most memory techniques is that the average brain remembers images far better than it remembers facts or figures; so if you can build a picture in your head - the crazier the better (the picture not the head) - you're more likely to remember it than trying to remember numbers, words or dates and times alone.
It's all fairly straight forward; you want to memorise a shopping list of milk, bread and chicken: think of a big cartoon chicken swimming around in a lake full of milk while you throw loafs of bread at it like it's some sort of funfair game. It's strange, it's vivid and it's likely to stay in your head - at least until you get to the shop.
The problem comes when you need to memorise numbers, as is often the case in this technology driven world - pin numbers, phone numbers, registration numbers, dates, etc. The trick is to encode the numbers into letters; there are various techniques you can use, but the one that I took a shine to is called the Mnemonic Major System. There are a couple of variations, but the Derren Brown system dictates:
As an example, let's imagine that your PIN number is 9283. Break it up and start with the number 92; this encodes as GN - pad this out with some vowels of your own choosing and you can end up with GUN, GIN, GOON, GENE, you get the idea?
I then choose to encode the final two digits (83) as JAM. Now I build a big, colourful mental image of a gun that squirts out jam. You can also add something to the picture to remember the context, so let's imagine you're standing in your local bank, sticking the place up (no pun intended) with this gun which goes off randomly, covering the bewildered bank clerks with jam. When you need to, you can break this picture down to the words, then unencode the words back into the numbers.
The part I find tricky is packing the vowels in to find a decent word I can picture. This is where the Powershell and regular expressions come into play. I figured that given the right regular expression and a big list of English words, I could have any matching words recommended to me. For example, given the letters GN I could use the following regular expression to match any words that fit:
^[aeiou]*G[aeiou]*N[aeiou]*$
It basically matches any word on a line of its own that contains zero or more vowels, followed by a G then zero or more vowels, then an N, then anymore vowels that might be lying around.
All we need now is a function that takes the letters you've encoded, builds the regular expression and then finds the matches from a text file full of words. I was about to take the easy route and build something in C#, but I figured this would be a good opportunity to get my head around Powershell.
$letters = "gn"
$vowel = "[aeiou]"
$regex = "^" + $vowel + "*"
foreach($char in [char[]]$letters) { $regex += $char + $vowel + "*" }
$regex += "$"
I declare my vowels in a regular expression character class - you can actually use any letters that don't match up to a number here, so adding in things like W and Y will likely increase the amount of words returned. Then using a foreach construct I wrap each of the letters provided in my character class.
At this point we have our regular expression pattern, all we need is a list of words and some code to find the matches. After a quick google I found a list of words designed to help people play scrabble: WordList.txt. We can now use the Powershell command Get-Content (or its shorter alias gc) to load the words, then iterate though them looking for a match with our regular expression:
gc "WordList.txt" | foreach { if([regex]::match($_, $regex).Success) { $_ } }
We pipe the contents of the dictionary into the foreach loop, which makes each word available in the $_ variable. If we get a successful match from the [regex] then we write the word out to the Powershell console with the simple statement: $_
Wrapping the whole thing up in a function, we have our finished article:
function GetWords([string]$letters)
{
$vowel = "[aeiouy]"
$regex = "^" + $vowel + "*"
foreach($char in [char[]]$letters) { $regex += $char + $vowel + "+" }
$regex = $regex.substring(0, $regex.length - 1)
$regex += "*$"
gc "WordList.txt" | foreach { if([regex]::match($_, $regex).Success) { $_ } }
}
Paste this into a Powershell console window and then call it with: GetWords("gn") and you'll receive the following recommendations:
again, agene, agin, agon, agone, agony, eugenia, gaen, gain,
gan, gane, gaun, gen, gene, genie, genii, genoa, genu, genua,
gien, gin, gone, gonia, goon, gooney, goonie, goony, guan,
guanay, guano, guinea, gun, iguana, oogeny, oogonia, yogin,
yogini
If you want to learn more about memory tricks I'd highly recommend Derren Brown's book Tricks of the Mind, and anything by Dominic O'Brien.
Tagged as: powershell, regex, memory,