-
Notifications
You must be signed in to change notification settings - Fork 1
/
werd.old.rb
143 lines (112 loc) · 3.71 KB
/
werd.old.rb
1
2
3
4
5
6
7
8
9
10
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#encoding:utf-8
# Random Word Generator with simple rules (see datafiles); recursive;
# details on datafile format can be found in the English ruleset;
# by Robert Kosek, robert.kosek@thewickedflea.com.
#
# Based on the Perl version by Chris Pound (pound@rice.edu), which was
# based on Mark Rosenfelder's Pascal implementation.
#
# Improvements:
# - Mutations via Regex! Now you can separate syllables with dashes
# and then perform substitution on it. (Limitation: the regex cannot
# contain / slashes.)
# - Optional sections can be wrapped in parenthesis!
# CV(N)C => CVC || CVNC
# - Nestable parenthesis, in case it becomes useful to someone.
# - Generation of an infinite series of words
# - Technical support for Unicode (touch not ye first line)
# - Vertical compaction with tab-delimited list instead of new-lines
srand Time.now.to_i
require 'ostruct'
require 'optparse'
fail "Requires Ruby 1.9.2" unless RUBY_VERSION == '1.9.2'
$options = OpenStruct.new
$options.number = 50
$options.seperator = "\n"
$options.mutate = false
$options.mdebug = false
$options.syllables = false
$rules = {}
$mutate = []
op = OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [FILE] [$options]"
$options.file = ARGV.first
opts.on("-n", "--number NUM", Integer, "How many words to generate") do |n|
$options.number = n
end
opts.on('-i', '--infinite', 'Generates an infinite set of words') do
$options.number = -1
end
opts.on('-c', '--compact', 'Seperates words with a tab') do
$options.seperator = "\t"
end
opts.on('-m', '--[no-]mutate', 'Perform derivation mutations') do |m|
$options.mutate = m
end
opts.on('--show-syllables', 'Leave syllable breaks in the output') do
$options.syllables = true
end
opts.on('--debug', 'Enable debug output') do
$options.mdebug = true
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end
begin
op.parse!
raise OptionParser::MissingArgument.new("[FILE] must be specified.") if $options.file.nil?
rescue
puts $!, op
exit
end
if $options.file && File.exist?($options.file)
File.open($options.file, 'r') do |f|
while !f.eof? && line = f.readline
case line
when /^([A-Z]):\s*([^#]*)\s*/
$rules[$1] = $2.strip.split(/\s+/)
when /^\/([^\/]+)\/\s+\>\s+"([^"]*?)"/
from = $~[1]
to = $~[2]
from.gsub!(/([\|&])([A-Z])/) do
$rules[$2].join( $1 == '|' ? '|' : '')
end
from = Regexp.new(from)
$mutate << [from, to]
end
end
end
end
def make_word rule="W"
pattern = $rules[rule][rand($rules[rule].length)].dup
# handle optional patterns
pattern.gsub!(/\(([^()]*?)\)/) { rand(100) < 50 ? $1 : '' }
# handle subpatterns
pattern.gsub!(/([A-Z])/) { make_word($1) }
# handle mutations
if $options.mutate && rule == 'W'
mrecord = [pattern.dup] if $options.mdebug
$mutate.each do |(from,to)|
pattern.gsub!(from, to);
mrecord << pattern.dup if $options.mdebug && rule == "W" && pattern != mrecord.last
end
puts mrecord.join(' => ') if $options.mdebug && mrecord.first != mrecord.last
end
pattern.gsub!('-', '') unless $options.syllables # remove syllable markers
pattern
end
werd = Enumerator.new do |result|
loop { result << make_word }
end
if $rules.size > 0
if $options.number == -1
puts "Generating an infinite set of words from #{File.basename($options.file)}"
werd.each { |w| print w, $options.seperator }
else
puts "Generating #{$options.number} words from #{File.basename($options.file)}"
werd.take($options.number).each { |w| print w, $options.seperator }
end
puts if $options.seperator == "\t"
end