--
lternative 006BBBB48525714C_Content-Type: text/plain; charset="US-ASCII"

# Author: Shane Emmons
#
# Quiz 74: Markov Chains
#
# This is a bug fix and enhancement to my previous solution.
# Originally this was a recreation of the Mark V. Shaney program.
# However, after extensive work it is something new. You can now
# choose how many words can be stored as a phrase (the default
# is 2). I have also stopped storing Hash keys in reverse order
# since it was hindering debugging. In doing this, I found other
# problems in the selection of words which is now fixed. If you
# see anything that is to wordy, wrong, or can be Rubified let
# me know.
#
# I was thinking, but have not tried, what would happen if you
# sent source code through the algorithm? Obviously some things
# would need to be changed for "phrase_breaks", but I wonder if
# anything would actually sucessfully run.

class MarkovChain

    def initialize( book, max_phrase_size   )
        @book  ook
        @phrases  rray.new( max_phrase_size )
        @phrases.each_index { |i| @phrases[ i ]  ash.new }
        @phrase_breaks  rray.new
    end

    def read( book  book )
        prev  rray.new( @phrases.length ).fill( '' )
        words  ile.open( book ).read.split
        words.each do |word|
            word.gsub!( /["()]/, '' )
            unless prev[ -1 ].eql?( '' )
                @phrases.each_index do |i|
                    prev_words  rev[ @phrases.length - i .. prev.length 
- 1 ].join( '' )
                    @phrases[ i ][ prev_words ]  rray.new unless
                        @phrases[ i ].has_key?( prev_words )
                    @phrases[ i ][ prev_words ] << word.downcase
                    @phrase_breaks << prev_words if prev_words.match( 
/[.!?]$/ )
                end
            end
            prev.shift and prev.push( word )
        end
    end

    def get_chain( num_want   )
        chain  rray.new
        num_made  
        prev  rray.new( @phrases.length ).fill( '' )
        prevs  rray.new( @phrases.length )
        prev.each_index do |i|
            prevs[ i ]  rev[ @phrases.length - i .. prev.length - 1 
].join( '' )
        end
        while num_made < num_want do
            found  alse
            @phrases.each_index do |i|
                found  rue if @phrases[ i ].has_key?( prevs[ i ] )
            end
            until found
                prev  phrase_breaks[ rand( @phrase_breaks.length ) 
].split
                prev << '' until prev.length @phrases.length
                prev.each_index do |i|
                    prevs[ i ]  rev[ @phrases.length - i .. prev.length 
- 1 ].join( '' )
                end
                @phrases.each_index do |i|
                    found  rue if @phrases[ i ].has_key?( prevs[ i ] )
                end
            end
            words  rray.new
            @phrases.each_index do |i|
                prev_words  rev[ @phrases.length - i .. prev.length - 1 
].join( '' )
                words  phrases[ i ][ prev_words ] if
                    @phrases[ i ].has_key?( prev_words )
            end
            word  ords[ rand( words.length ) ]
            chain << word
            prev.shift and prev.push( word )
            prev.each_index do |i|
                prevs[ i ]  rev[ @phrases.length - i .. prev.length - 1 
].join( '' )
            end
            num_made +  if word.match( /[.!?]$/ )
        end
        chain
    end
 
end

mChain  arkovChain.new( ARGV[ 0 ] )
mChain.read
print mChain.get_chain.join( ' ' ), "\n"

--
lternative 006BBBB48525714C_