From: Eugene Kalenkovich Date: 2009-03-11T13:03:05+09:00 Subject: Re: [QUIZ] Rhyming Words (#195) "Daniel Moore" wrote in message news:89672ce30903060825v33c1264eva295783120c794b4@mail.gmail.com... > > ## Rhyming Words (#195) > > Salutations fellow Rubyists, > > This weeks quiz comes courtesy of Redd Vinylene: > > > How do I match words that rhyme, like end rhymes, last syllable > > rhymes, double rhymes, beginning rhymes and first syllable rhymes? > > > > Like rhymer.com. I'm looking to improve my freestyle skills :) > > > > http://www.youtube.com/watch?v=SmqXKbxDoJ0 > > Your task is to create a Ruby program that when given a word and a > type of rhyme (end rhymes, last syllable rhymes, double rhymes, > beginning rhymes, first syllable rhymes) returns a list of rhyming > words. > > Have Fun! >----------------------------------------------------------------------------------- My solution takes the quiz idea, but not really its requirements :) I've decided to drop the syllable-based rhymes only at first, as they asked for a pretty cumbersome pieces of code. After implementing and trying it out I've found that to my own taste _all_ types of rhymes described at rhymer.com do not add enough to behavior to grant complications of code, so I've cleaned them out too :) My final solution is limited to perfect and identical rhymes only. First two commented lines - commands to run before to make it work. You can see this working at http://gamewords.herokugarden.com/ # wget http://www.dcs.shef.ac.uk/research/ilash/Moby/mpron.tar.Z # tar zxvf mpron.tar.Z $words = Hash.new{|h,k| h[k]=[]} $rhymes = Hash.new{|h,k| h[k]=[]} def perfect_key(pron) key = [] pron.reverse.each do |snd| key << snd break if snd =~ /1$/ end key end def rhymes(word) wup = word.upcase $rhymes[perfect_key($words[wup])] - [wup] end File.open('mpron/cmudict0.3') {|f| f.readlines}.each do |l| w, *pron = l.strip.split(' ') next unless !w.empty? and w.grep(/[^A-Z]/).empty? pron.map!{|sound| sound.sub(/2/,'1')} $words[w]=pron $rhymes[perfect_key(pron)] << w end input = ARGV.empty? ? ['laughter', 'soaring', 'antelope'] : ARGV print input.map{|w| w+': '+rhymes(w).map(&:downcase).join(', ')+"\n"}.join("\n")