[SUMMARY] Rhyming Words (#195)

Discussion in 'Ruby' started by Daniel Moore, Mar 15, 2009.

  1. Daniel Moore

    Daniel Moore Guest

    This week's quiz had an excellent solution from Eugene Kalenkovich.

    In order to get this to work on my machine in 1.8 or 1.9 I had to add
    the following:

    # Adding 1.9 and 1.8 compatibility
    if :a.respond_to? :to_proc
    class String
    include Enumerable
    alias :each :each_line
    end
    else
    class Symbol
    def to_proc
    proc { |obj, *args| obj.send(self, *args) }
    end
    end
    end

    This is probably not the best overall solution to make code 1.9
    compatible, but it does illustrate some of the differences between
    Ruby versions. It appears as though the code was written for 1.8 but
    with Facets or another library defining `Symbol#to_proc`.

    Eugene's solution requires a database (plain text file of words and
    pronunciations) to operate. The file contains entries in the following
    form:

    # ...
    MONGOLS M AA1 NG G AH0 L Z
    MONGOOSE M AA1 NG G UW0 S
    # ...
    REPARATIONS R EH2 P ER0 EY1 SH AH0 N Z
    REPARTEE R EH2 P ER0 T IY1
    # ...

    These are phonetic representations of the words. The readme file that
    accompanies the database describes the pronunciations in detail if you
    are interested in learning more.

    # lookup tables to store the words and rhyming words
    $words = Hash.new{|h,k| h[k]=[]}
    $rhymes = Hash.new{|h,k| h[k]=[]}

    The `perfect_key` method is what determines what words perfectly rhyme
    with one another. It iterates through the reverse of the sound list
    and stops after adding the first stress. So if the word is 'mongoose'
    `perfect_key` will return `["S", "UW0", "G", "NG", "AA1"]`.

    # Returns an array of sounds starting at the end and
    # going through the first stress
    def perfect_key(pron)
    key = []
    pron.reverse.each do |snd|
    key << snd
    break if snd =~ /1$/
    end
    key
    end

    The rhymes method is used to display the rhyming words in the output.
    It gets all the rhyming words for the given word's perfect key and
    returns the list minus the word itself.

    def rhymes(word)
    wup = word.upcase
    $rhymes[perfect_key($words[wup])] - [wup]
    end

    Reading the data file and creating the tables of pronunciation and
    words is the bulk of the processing. This section iterates through
    each line in the word data file and creates a mapping from the word to
    the pronunciation, skipping comment lines or lines that have words
    with non-alpha characters. After mapping the word to the pronunciation
    it adds the word to the list of rhymes that is mapped by the perfect
    key of the pronunciation in the `$rhymes` hash.

    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

    The program will find rhymes for all command line arguments passed in,
    or some example arguments if none are given. Having already loaded the
    data into a mapping that is convenient, all that is left is to lookup
    the lists of words that match the given words perfect rhymes and print
    them out.

    input = ARGV.empty? ? ['laughter', 'soaring', 'antelope'] : ARGV
    results = input.map do |w|
    w + ': ' + rhymes(w).map(&:downcase).join(', ') + "\n"
    end.join("\n")

    print results

    Thank you, Eugene, for a very cool solution!

    http://rubyquiz.strd6.com/quizzes/195

    - Daniel
     
    Daniel Moore, Mar 15, 2009
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Strøiman
    Replies:
    1
    Views:
    2,118
    Peter Strøiman
    Aug 23, 2005
  2. Richard Heathfield
    Replies:
    7
    Views:
    384
    Barry Schwarz
    Oct 5, 2003
  3. Tim Daneliuk
    Replies:
    0
    Views:
    273
    Tim Daneliuk
    Feb 17, 2005
  4. utab

    Words Words

    utab, Feb 16, 2006, in forum: C++
    Replies:
    6
    Views:
    439
    Daniel T.
    Feb 16, 2006
  5. Ciaran
    Replies:
    0
    Views:
    635
    Ciaran
    Apr 19, 2007
Loading...

Share This Page