My wife recently developed an interest in semordnilaps, so I thought I would take a stab at writing a script that will find some. What I came up with finds a subset of all two word to two word semordnilaps. Generally you don’t consider whitespace and punctuation in palindromes and semordnilaps, so this code doesn’t either.
It turns out that filtering out proper names vastly reduces the number of semordnilaps found, and I didn’t really appreciate the ones which contained proper names anyway, so I took those out.
words = {} File.open("/usr/share/dict/words") do |file| file.each do |line| if line.length > 4 # don't accept one or two letter words. word = line.strip next if word.downcase != word # proper names have capitals, exclude those. words[word.downcase.gsub(/[^a-z]/, '')] = true end end end words.each do |word1, k| p_words = {} word_finds = 0 word1 = word1.reverse first_words = [] # skip words that when reversed don't match the ending of another word. (1 .. (word1.length - 1)).each do |i| if words[word1[0..i]] first_words << word1[0..i] end end if first_words.count == 0 next end words.each do |word2, k| two_words = word1 + word2.reverse (2 .. two_words.length).each do |i| if words[two_words[0..(i - 1)]] && words[two_words[i..(two_words.length-1)]] p_words[two_words[0..(i - 1)] + ' ' + two_words[i..(two_words.length-1)]] = word2 + ' ' + word1.reverse word_finds += 1 end end end if word_finds > 0 puts p_words end end
And this gives you some great semordnilaps like:
- “cite catnip”=>”pint acetic”
- “stub aloof”=>”fool abuts”
- “tubas gals”=>”slags abut”
- “sane railed”=>”deli arenas”
- “reis trailed”=>”deli artsier”
- “diva lived”=>”devil avid”
- “stabs faced”=>”decafs bats”
All told, I got a 2.7MB text file. I am sure that there are better ones in there.