--
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_