marky_markov 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -4,6 +4,11 @@ Marky Markov and the Funky Sentences
4
4
  Marky Markov is a naïve experiment in Markov Chain generation implemented
5
5
  in Ruby. It can be used both from the command-line and as a library within your code.
6
6
 
7
+ NOTE: In the transition between 0.1.3 to 0.2.0 MarkyMarkov has added the
8
+ ability to generate proper sentences (generate_n_sentences) instead of simply a
9
+ maximum number of words. The command-line app has changed to sentences as its default
10
+ behavior.
11
+
7
12
  # Installation
8
13
 
9
14
  gem install marky_markov
@@ -17,8 +22,8 @@ temporary dictionary that will not be saved to disk.
17
22
  markov = MarkyMarkov::TemporaryDictionary.new
18
23
  markov.parse_string "These words will be added to the temporary dictionary."
19
24
  markov.parse_file "filename.txt"
20
- puts markov.generate_n_words 50
21
- puts markov.generate_n_words 3000
25
+ puts markov.generate_n_sentences 5
26
+ puts markov.generate_n_words 200
22
27
  markov.clear!
23
28
 
24
29
  Dictionary creates or opens a persistent dictionary at a location defined by its
@@ -31,18 +36,22 @@ of the dictionary name.
31
36
  markov.parse_file "ENV["HOME"]/Documents/largefileindocs.txt"
32
37
  markov.parse_file "anotherfileyay.txt"
33
38
  puts markov.generate_n_words 10
39
+ puts markov.generate_n_sentences 2
34
40
  markov.save_dictionary! # Saves the modified dictionary/creates one if it didn't exist.
35
41
 
36
- If you keep looking at generate_n_words and wonder why you can't put a
42
+ If you keep looking at generate_n_words or generate_n_sentences and wonder why you can't put a
37
43
  number in there, well, you can!
38
44
 
45
+ markov.generate_7_sentences
39
46
  markov.generate_20_words
40
47
 
41
48
  The default dictionary depth is two words.
42
49
  `{"I hope" => {"this" => 1},
43
50
  "hope this" => {"makes" => 1},
44
51
  "this makes" => {"sense" => 1}}`
45
- but it can be set to a depth between 1 and 9 upon dictionary creation
52
+ but it can be set to a depth between 1 and 5 upon dictionary creation,
53
+ though really any higher than 3 and it starts to simply print passages
54
+ from the source text.
46
55
 
47
56
  markov = MarkyMarkov::Dictionary.new('dictionary', 3)
48
57
 
@@ -72,18 +81,18 @@ on different files to continue adding to your dictionary file.
72
81
 
73
82
  ## Say Some Words
74
83
 
75
- marky_markov speak -w 30
84
+ marky_markov speak -c 3
76
85
 
77
- Will use the dictionary to create a 30 word long sentence. If no number
78
- is passed it will default to 200 words.
86
+ Will use the dictionary to create three sentences. If no number
87
+ is passed it will default to five sentences..
79
88
 
80
89
  ## Temporary Dictionaries
81
90
 
82
- marky_markov speak -s other-file.txt -w 20
91
+ marky_markov speak -s other-file.txt -c 8
83
92
 
84
93
  Generates a temporary dictionary based on the source file passed to it
85
94
  and uses that to speak. Here we're loading other-file.txt and
86
- restricting the generated sentence to 20 words.
95
+ restricting the generated text to 8 sentences.
87
96
 
88
97
  ## STDIN, Pipe Away!
89
98
 
@@ -99,12 +108,15 @@ though the results are nonsense without a substantial text base to work
99
108
  from.
100
109
 
101
110
  Usage: marky_markov COMMAND [OPTIONS]
102
- Commands:
103
- speak: Generate Markov Chain sentence (default wordcount of 200)
104
- listen [sentence]: Generate Markov Chain sentence from supplied string.
105
- read [file]: Add words to dictionary from supplied text file
106
- Options
107
- -d, --dictionary FILE Use custom dictionary location
108
- -w, --wordcount NUMBER Set number of words generated
109
- -s, --source FILE Generate and use temporary dictionary from source text
110
- -h, --help Display this screen
111
+
112
+ Commands:
113
+ speak: Generate Markov Chain sentence (5 sentences by default)
114
+ listen [sentence]: Generate Markov Chain sentence from supplied string.
115
+ read [file]: Add words to dictionary from supplied text file
116
+
117
+ Options
118
+ -d, --dictionary LOCATION Use custom dictionary location
119
+ -c, --sentencecount NUMBER Set number of sentences generated
120
+ -s, --source FILE Generate and use temporary dictionary from source text
121
+ --reset WARNING: Deletes default dictionary.
122
+ -h, --help Display this screen
data/bin/marky_markov CHANGED
@@ -6,23 +6,23 @@ require 'marky_markov'
6
6
 
7
7
  options = {}
8
8
  opt_parser = OptionParser.new do |opts|
9
- opts.banner = "Usage: marky-markov COMMAND [OPTIONS]"
9
+ opts.banner = "Usage: marky_markov COMMAND [OPTIONS]"
10
10
  opts.separator ""
11
11
  opts.separator "Commands:"
12
- opts.separator " speak: Generate Markov Chain sentence (default wordcount of 200)"
12
+ opts.separator " speak: Generate Markov Chain sentence (5 sentences by default)"
13
13
  opts.separator " listen [sentence]: Generate Markov Chain sentence from supplied string."
14
14
  opts.separator " read [file]: Add words to dictionary from supplied text file"
15
15
  opts.separator ""
16
16
  opts.separator "Options"
17
17
 
18
18
  options[:dictionary] = "#{ENV["HOME"]}/.marky_markov_dictionary"
19
- opts.on('-l', '--location DICTIONARY', 'Use custom dictionary location') do |file|
19
+ opts.on('-d', '--dictionary LOCATION', 'Use custom dictionary location') do |file|
20
20
  options[:dictionary] = file
21
21
  end
22
22
 
23
- options[:wordcount] = 200
24
- opts.on('-w', '--wordcount NUMBER', 'Set number of words generated') do |number|
25
- options[:wordcount] = number.to_i
23
+ options[:sentencecount] = 5
24
+ opts.on('-c', '--sentencecount NUMBER', 'Set number of sentences generated') do |number|
25
+ options[:sentencecount] = number.to_i
26
26
  end
27
27
 
28
28
  options[:source] = nil
@@ -31,12 +31,6 @@ opt_parser = OptionParser.new do |opts|
31
31
  options[:source] = file
32
32
  end
33
33
 
34
- options[:depth] = 2
35
- opts.on('-d', '--depth 1-9', 'Set dictionary depth. The higher the number
36
- , the less random the sentence will be. Must be between 1 and 9.') do |number|
37
- options[:depth] = number.to_i
38
- end
39
-
40
34
  options[:resetdictionary] = false
41
35
  opts.on('--reset', "WARNING: Deletes default dictionary." ) do
42
36
  options[:resetdictionary] = true
@@ -58,7 +52,7 @@ end
58
52
  case ARGV[0]
59
53
  when "speak"
60
54
  if options[:source]
61
- markov = MarkyMarkov::TemporaryDictionary.new(options[:depth])
55
+ markov = MarkyMarkov::TemporaryDictionary.new
62
56
  markov.parse_file(options[:source])
63
57
  else
64
58
  unless File.exists?("#{options[:dictionary]}.mmd")
@@ -68,22 +62,22 @@ when "speak"
68
62
  end
69
63
  markov = MarkyMarkov::Dictionary.new(options[:dictionary])
70
64
  end
71
- STDOUT.puts markov.generate_n_words(options[:wordcount])
65
+ STDOUT.puts markov.generate_n_sentences(options[:sentencecount])
72
66
  when "read"
73
67
  source = ARGV[1] || options[:source]
74
- markov = MarkyMarkov::Dictionary.new(options[:dictionary], options[:depth])
68
+ markov = MarkyMarkov::Dictionary.new(options[:dictionary])
75
69
  markov.parse_file(source)
76
70
  markov.save_dictionary!
77
71
  STDOUT.puts "Added #{source} to dictionary."
78
72
  when "listen"
79
73
  markov = MarkyMarkov::TemporaryDictionary.new
80
74
  markov.parse_string(STDIN.tty? ? ARGV[1] : STDIN.read)
81
- STDOUT.puts markov.generate_n_words(options[:wordcount])
75
+ STDOUT.puts markov.generate_n_sentences(options[:sentencecount])
82
76
  else
83
77
  unless STDIN.tty?
84
- markov = MarkyMarkov::TemporaryDictionary.new(options[:depth])
78
+ markov = MarkyMarkov::TemporaryDictionary.new
85
79
  markov.parse_string(STDIN.read)
86
- STDOUT.puts markov.generate_n_words(options[:wordcount])
80
+ STDOUT.puts markov.generate_n_sentences(options[:sentencecount])
87
81
  else
88
82
  STDOUT.puts opt_parser
89
83
  end
data/lib/marky_markov.rb CHANGED
@@ -4,12 +4,12 @@
4
4
  require_relative 'marky_markov/persistent_dictionary'
5
5
  require_relative 'marky_markov/markov_sentence_generator'
6
6
 
7
- # @version = 0.1.3
7
+ # @version = 0.2.0
8
8
  # @author Matt Furden
9
9
  # Module containing TemporaryDictionary and Dictionary for creation of
10
10
  # Markov Chain Dictionaries and generating sentences from those dictionaries.
11
11
  module MarkyMarkov
12
- VERSION = '0.1.3'
12
+ VERSION = '0.2.0'
13
13
 
14
14
  class TemporaryDictionary
15
15
  # Create a new Temporary Markov Chain Dictionary and sentence generator for use.
@@ -49,39 +49,62 @@ module MarkyMarkov
49
49
  #
50
50
  # @example Generate a 40 word long string of words.
51
51
  # markov.generate_n_words(40)
52
+ # @example Generate a 10 word long string of words with method_missing.
53
+ # markov.generate_10_words
52
54
  # @param [Int] wordcount the number of words you want generated.
53
55
  # @return [String] the sentence generated by the dictionary.
54
56
  def generate_n_words(wordcount)
55
57
  @sentence.generate(wordcount)
56
58
  end
57
59
 
58
- # Dynamically call generate_n_words if an Int is substituted for
59
- # the n in the method call.
60
+ # Generates n sentences using the dictionary generated via
61
+ # parse_string or parse_file. A sentence is defined as beginning with a
62
+ # capitalized word and ending with either a . ! or ?
60
63
  #
61
- # @since 0.1.2
64
+ # @since 0.2.0
65
+ # @example Generate three sentences.
66
+ # markov.generate_n_sentences(3)
67
+ # @example Generate six sentences with method_missing.
68
+ # markov.generate_6_sentences
69
+ # @param [Int] wordcount the number of sentences you want generated.
70
+ # @return [String] the sentences generated by the dictionary.
71
+ def generate_n_sentences(sentencecount)
72
+ @sentence.generate_sentence(sentencecount)
73
+ end
74
+
75
+ # Dynamically call generate_n_words or generate_n_sentences
76
+ # if an Int is substituted for the n in the method call.
77
+ #
78
+ # @since 0.1.4
62
79
  # @example Generate a 40 and a 1 word long string of words.
63
80
  # markov.generate_40_words
64
81
  # markov.generate_1_word
82
+ # @example Generate 2 sentences
83
+ # markov.generate_2_sentences
65
84
  # @return [String] the sentence generated by the dictionary.
66
85
  def method_missing(method_sym, *args, &block)
67
86
  if method_sym.to_s =~ /^generate_(\d*)_word[s]*$/
68
87
  generate_n_words($1.to_i)
88
+ elsif method_sym.to_s =~ /^generate_(\d*)_sentence[s]*$/
89
+ generate_n_sentences($1.to_i)
69
90
  else
70
91
  super
71
92
  end
72
93
  end
73
94
 
74
- # @since 0.1.2
75
- # Modify respond_to? to include generate_n_words method_missing implementation.
95
+ # @since 0.1.4
96
+ # Modify respond_to? to include generate_n_words and generate_n_sentences
97
+ # method_missing implementation.
76
98
  def respond_to?(method_sym, include_private = false)
77
99
  if method_sym.to_s =~ /^generate_(\d*)_word[s]*$/
78
- true
100
+ generate_n_words($1.to_i)
101
+ elsif method_sym.to_s =~ /^generate_(\d*)_sentence[s]*$/
102
+ generate_n_sentences($1.to_i)
79
103
  else
80
104
  super
81
105
  end
82
106
  end
83
107
 
84
-
85
108
  # Clears the temporary dictionary's hash, useful for keeping
86
109
  # the same dictionary object but removing the words it has learned.
87
110
  #
@@ -20,13 +20,17 @@ class MarkovSentenceGenerator
20
20
  # dictionary and recurring if the word is lowercase.
21
21
  #
22
22
  # (see #random_word)
23
- def random_capitalized_word
23
+ def random_capitalized_word(attempts=0)
24
24
  keys = @dictionary.dictionary.keys
25
25
  x = keys[rand(keys.length)]
26
26
  if /[A-Z]/ =~ x[0]
27
27
  return x
28
+ elsif attempts < 30
29
+ # If you don't find a capitalized word after 30 attempts, just use
30
+ # a lowercase word as there may be no capitals in the dicationary.
31
+ random_capitalized_word(attempts+1)
28
32
  else
29
- random_capitalized_word
33
+ random_word
30
34
  end
31
35
  end
32
36
 
@@ -49,6 +53,8 @@ class MarkovSentenceGenerator
49
53
 
50
54
  # Generates a sentence of (wordcount) length using the weighted_random function.
51
55
  #
56
+ # @param [Int] wordcount The number of words you want the generated string to contain.
57
+ # @return [String] the words, hopefully forming sentences generated.
52
58
  def generate(wordcount)
53
59
  sentence = []
54
60
  sentence.concat(random_capitalized_word.split)
@@ -58,4 +64,27 @@ class MarkovSentenceGenerator
58
64
  sentence.pop(sentence.length-wordcount)
59
65
  sentence.join(' ')
60
66
  end
67
+
68
+ # Generates a (sentencecount) sentences using the weighted_random function.
69
+ #
70
+ # @param [Int] sentencecount The number of sentences you want the generated string to contain.
71
+ # @return [String] the sentence(s) generated.
72
+ def generate_sentence(sentencecount)
73
+ sentence = []
74
+ sentencecount.times do
75
+ # Find out how many actual keys are in the dictionary.
76
+ key_count = @dictionary.dictionary.keys.length
77
+ # If less than 30 keys, use that plus five as your maximum sentence length.
78
+ maximum_length = key_count < 30 ? key_count + 5 : 30
79
+ stop_at_index = sentence.count + maximum_length
80
+ sentence.concat(random_capitalized_word.split)
81
+ until (/[.!?]/ =~ sentence.last[-1])
82
+ sentence.concat(weighted_random(sentence.last(@depth).join(' ')).split)
83
+ # If a word ending with a . ! or ? isn't found after 30 words,
84
+ # just add a period as there may be none in the dictionary.
85
+ sentence[-1] << "." if sentence.count > stop_at_index
86
+ end
87
+ end
88
+ sentence.join(' ')
89
+ end
61
90
  end
@@ -15,8 +15,8 @@ class PersistentDictionary < MarkovDictionary
15
15
  attr_reader :dictionarylocation, :depth
16
16
  def initialize(dictionary, depth=2)
17
17
  @depth = depth
18
- unless (1..9).include?(depth)
19
- raise DepthNotInRangeError.new("Depth must be between 1 and 9")
18
+ unless (1..5).include?(depth)
19
+ raise DepthNotInRangeError.new("Depth must be between 1 and 5")
20
20
  end
21
21
  @dictionarylocation = dictionary
22
22
  self.open_dictionary
data/spec/test.txt ADDED
@@ -0,0 +1 @@
1
+ The cat likes pie and chainsaws
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marky_markov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yajl-ruby
16
- requirement: &70361383496140 !ruby/object:Gem::Requirement
16
+ requirement: &70254574670860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -24,7 +24,7 @@ dependencies:
24
24
  version: 2.0.0
25
25
  type: :runtime
26
26
  prerelease: false
27
- version_requirements: *70361383496140
27
+ version_requirements: *70254574670860
28
28
  description: ! "MarkyMarkov makes it easy to generate simply Markov Chains based upon
29
29
  input from\n either a source file or a string. While usable as a module in your
30
30
  code it can also be called on\n from the command line and piped into like a standard
@@ -46,6 +46,7 @@ files:
46
46
  - spec/marky_markov/markov_sentence_generator_spec.rb
47
47
  - spec/marky_markov/persistent_dictionary_spec.rb
48
48
  - spec/spec_helper.rb
49
+ - spec/test.txt
49
50
  - spec/textdictcompare.mmd
50
51
  homepage: http://www.thefurd.com
51
52
  licenses: []