Class: MarkovChain

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/markov_chain.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMarkovChain

Returns a new instance of MarkovChain.



82
83
84
# File 'lib/markov_chain.rb', line 82

def initialize
  @chars = Hash.new
end

Class Method Details

.dictionaryObject



77
78
79
# File 'lib/markov_chain.rb', line 77

def dictionary
  @dictionary
end

.dictionary_loaded?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/markov_chain.rb', line 73

def dictionary_loaded?
  !!@dictionary_loaded
end

.grow_string(seed, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/markov_chain.rb', line 11

def grow_string seed, options = {}
  raise ArgumentError, 'Seed must be at least two characters' unless seed.length > 1

  max_word_length = seed.length + 8

  defaults = {
    :max_size => 100,
    :max_word_length => max_word_length,
    :max_retries => 1000
  }

  options = defaults.merge options

  load_dictionary! unless dictionary_loaded?

  words = [seed]
  old_words = []
  retries = 0

  mc = MarkovChain.instance

  while words.length < options[:max_size] && retries < options[:max_retries] do
    old_words = words.dup
    word = seed.dup
    old_word = ''

    while word.length < options[:max_word_length] && word != old_word
      old_word = word.dup
      word << mc.get(word.slice(word.length - 1, 1))
      words.push word.dup
    end

    words = words.map { |w| w.gsub(/[^a-z]/, '') }.uniq

    retries += 1 if words == old_words
  end

  words = words[0..(options[:max_size] - 1)]

  words.sort { |a, b| a.length <=> b.length }
end

.instanceObject



7
8
9
# File 'lib/markov_chain.rb', line 7

def instance
  @__instance__ ||= new
end

.load_dictionary!(file = :american_english) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/markov_chain.rb', line 53

def load_dictionary! file = :american_english
  if file.class == Symbol
    file = File.join File.dirname(__FILE__), 'dictionaries', file.to_s
  end

  dictionary = File.new file, 'r:ASCII-8BIT'

  if dictionary
    while (line = dictionary.gets)
      s = line.strip
      instance.add_str s
    end

    @dictionary_loaded = true
    @dictionary = File.expand_path file

    dictionary.close
  end
end

Instance Method Details

#add(char, next_char) ⇒ Object



94
95
96
97
# File 'lib/markov_chain.rb', line 94

def add char, next_char
  @chars[char] = Hash.new(0) if !@chars[char]
  @chars[char][next_char] += 1
end

#add_str(str) ⇒ Object



86
87
88
89
90
91
92
# File 'lib/markov_chain.rb', line 86

def add_str str
  index = 0
  each_char(str) do |char|
    add(char, str[index + 1]) if index <= str.size - 2
    index += 1
  end
end

#get(char) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/markov_chain.rb', line 99

def get char
  return '' if !@chars[char]

  followers = @chars[char]
  sum = followers.inject(0) { |sum,kv| sum += kv[1] }
  random = rand(sum) + 1
  partial_sum = 0

  next_char = followers.find do |char, count|
    partial_sum += count
    partial_sum >= random
  end.first

  next_char
end