# Re: Markov Chain (#74)

**URL:** <https://www.ruby-forum.com/t/re-markov-chain-74/93804>\
**Category:** Ruby\
**Created:** [April 10, 2006, 9:38pm UTC](https://www.ruby-forum.com/t/re-markov-chain-74/93804 "2006-04-10T21:38:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [April 10, 2006, 9:38pm UTC](https://www.ruby-forum.com/t/re-markov-chain-74/93804/1 "2006-04-10T21:38:02Z")

</div>

# Author: Shane E.

# 

# 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 = 2 )
    @book = book
    @phrases = Array.new( max_phrase_size )
    @phrases.each_index { |i| @phrases[i] = Hash.new }
    @phrase_breaks = Array.new
end

def read( book = @book )
    prev = Array.new( @phrases.length ).fill( '' )
    words = File.open( book ).read.split
    words.each do |word|
        word.gsub!( /["()]/, '' )
        unless prev[-1].eql?( '' )
            @phrases.each_index do |i|
                prev_words = prev[ @phrases.length - i .. 

```

prev.length

- 1 ].join( ‘’ )  
@phrases[i][prev\_words] = Array.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

- 1 ].join( ‘’ )  
end  
@phrases.each\_index do |i|  
found = true if @phrases[i].has\_key?( prevs[i] )  
end  
end  
words = Array.new  
@phrases.each\_index do |i|  
prev\_words = prev[ @phrases.length - i … prev.length -  
1  
].join( ‘’ )  
words = @phrases[i][prev\_words] if  
@phrases[i].has\_key?( prev\_words )  
end  
word = words[rand( words.length )]  
chain \<\< word  
prev.shift and prev.push( word )  
prev.each\_index do |i|  
prevs[i] = prev[ @phrases.length - i … prev.length -  
1  
].join( ‘’ )  
end  
num\_made += 1 if word.match( /[.!?]$/ )  
end  
chain  
end

end

mChain = MarkovChain.new( ARGV[0] )  
mChain.read  
print mChain.get\_chain.join( ’ ’ ), “\n”
