numbers_in_words 0.1.0 → 0.1.1
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/Manifest +0 -1
- data/README +16 -2
- data/Rakefile +33 -3
- data/lib/numbers.rb +215 -192
- data/lib/numbers_in_words.rb +0 -1
- data/lib/words.rb +192 -197
- data/numbers_in_words.gemspec +12 -13
- data/spec/numbers_in_words_spec.rb +85 -81
- data/spec/words_in_numbers_spec.rb +108 -101
- metadata +38 -53
data/lib/words.rb
CHANGED
@@ -1,222 +1,217 @@
|
|
1
1
|
module WordsInNumbers
|
2
|
+
def in_numbers
|
3
|
+
text = to_s
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
"eleven"=>11,
|
8
|
-
"twelve"=>12,
|
9
|
-
"thirteen"=>13,
|
10
|
-
"fourteen"=>14,
|
11
|
-
"fifteen"=>15,
|
12
|
-
"sixteen"=>16,
|
13
|
-
"seventeen"=>17,
|
14
|
-
"eighteen"=>18,
|
15
|
-
"nineteen"=>19,
|
16
|
-
"twenty"=>20,
|
17
|
-
"thirty"=>30,
|
18
|
-
"forty"=>40,
|
19
|
-
"fifty"=>50,
|
20
|
-
"sixty"=>60,
|
21
|
-
"seventy"=>70,
|
22
|
-
"eighty"=>80,
|
23
|
-
"ninety"=>90
|
24
|
-
}
|
25
|
-
|
26
|
-
|
27
|
-
POWERS_OF_TEN ={
|
28
|
-
"one"=>0,
|
29
|
-
"ten"=> 1 ,
|
30
|
-
"hundred"=> 2,
|
31
|
-
"thousand"=> 3 ,
|
32
|
-
"million"=> 6,
|
33
|
-
"billion"=> 9,
|
34
|
-
"trillion"=> 12,
|
35
|
-
"quadrillion"=> 15,
|
36
|
-
"quintillion"=> 18,
|
37
|
-
"sextillion"=> 21,
|
38
|
-
"septillion"=> 24,
|
39
|
-
"octillion"=> 27,
|
40
|
-
"nonillion"=> 30,
|
41
|
-
"decillion"=> 33,
|
42
|
-
"undecillion"=> 36,
|
43
|
-
"duodecillion"=> 39,
|
44
|
-
"tredecillion"=> 42,
|
45
|
-
"quattuordecillion"=> 45,
|
46
|
-
"quindecillion"=> 48,
|
47
|
-
"sexdecillion"=> 51,
|
48
|
-
"septendecillion"=> 54,
|
49
|
-
"octodecillion"=> 57,
|
50
|
-
"novemdecillion"=> 60,
|
51
|
-
"vigintillion"=> 63,
|
52
|
-
"unvigintillion"=> 66,
|
53
|
-
"duovigintillion"=> 69,
|
54
|
-
"trevigintillion"=> 72,
|
55
|
-
"quattuorvigintillion"=> 75,
|
56
|
-
"quinvigintillion"=> 78,
|
57
|
-
"sexvigintillion"=> 81,
|
58
|
-
"septenvigintillion"=> 84,
|
59
|
-
"octovigintillion"=> 87,
|
60
|
-
"novemvigintillion"=> 90,
|
61
|
-
"trigintillion"=> 93,
|
62
|
-
"untrigintillion"=> 96,
|
63
|
-
"duotrigintillion"=> 99,
|
64
|
-
"googol"=> 100
|
65
|
-
}
|
66
|
-
|
67
|
-
def strip_punctuation text
|
68
|
-
#ignore punctuation
|
69
|
-
text.downcase!
|
70
|
-
text.gsub! /[^a-z ]/, " "
|
71
|
-
to_remove = true
|
72
|
-
until to_remove.nil?
|
73
|
-
to_remove=text.gsub! " ", " " until to_remove.nil?
|
74
|
-
end
|
75
|
-
return text
|
76
|
-
end
|
5
|
+
WordToNumber.new.instance_eval do
|
6
|
+
text = strip_punctuation text
|
7
|
+
#negative numbers
|
8
|
+
return -1 * (text.gsub(/^minus /, "")).in_numbers if text =~ /^minus /
|
77
9
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
decimal = "0." + integers.join()
|
82
|
-
decimal.to_f
|
83
|
-
end
|
10
|
+
#easy single word case
|
11
|
+
word = word_to_integer(text)
|
12
|
+
return word unless word.nil?
|
84
13
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
14
|
+
#decimals
|
15
|
+
match = text.match(/\spoint\s/)
|
16
|
+
if match
|
17
|
+
integer = match.pre_match.in_numbers
|
18
|
+
|
19
|
+
decimal = decimal_portion match.post_match
|
92
20
|
|
93
|
-
|
94
|
-
|
95
|
-
return word unless word.nil?
|
21
|
+
return integer + decimal
|
22
|
+
end
|
96
23
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
integer = match.pre_match
|
101
|
-
integer = integer.in_numbers
|
24
|
+
#multiple word case
|
25
|
+
words = text.split " "
|
26
|
+
integers = word_array_to_integers words
|
102
27
|
|
103
|
-
|
104
|
-
|
105
|
-
return
|
28
|
+
integer= parse_numbers(integers)
|
29
|
+
return integer unless integer.nil?
|
30
|
+
return nil
|
106
31
|
end
|
32
|
+
end
|
107
33
|
|
108
|
-
|
109
|
-
|
110
|
-
|
34
|
+
class WordToNumber
|
35
|
+
DIGITS= %w[zero one two three four five six seven eight nine]
|
36
|
+
|
37
|
+
EXCEPTIONS = {
|
38
|
+
"ten" => 10,
|
39
|
+
"eleven" => 11,
|
40
|
+
"twelve" => 12,
|
41
|
+
"thirteen" => 13,
|
42
|
+
"fourteen" => 14,
|
43
|
+
"fifteen" => 15,
|
44
|
+
"sixteen" => 16,
|
45
|
+
"seventeen" => 17,
|
46
|
+
"eighteen" => 18,
|
47
|
+
"nineteen" => 19,
|
48
|
+
"twenty" => 20,
|
49
|
+
"thirty" => 30,
|
50
|
+
"forty" => 40,
|
51
|
+
"fifty" => 50,
|
52
|
+
"sixty" => 60,
|
53
|
+
"seventy" => 70,
|
54
|
+
"eighty" => 80,
|
55
|
+
"ninety" => 90
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
POWERS_OF_TEN ={
|
60
|
+
"one" => 0,
|
61
|
+
"ten" => 1 ,
|
62
|
+
"hundred" => 2,
|
63
|
+
"thousand" => 3 ,
|
64
|
+
"million" => 6,
|
65
|
+
"billion" => 9,
|
66
|
+
"trillion" => 12,
|
67
|
+
"quadrillion" => 15,
|
68
|
+
"quintillion" => 18,
|
69
|
+
"sextillion" => 21,
|
70
|
+
"septillion" => 24,
|
71
|
+
"octillion" => 27,
|
72
|
+
"nonillion" => 30,
|
73
|
+
"decillion" => 33,
|
74
|
+
"undecillion" => 36,
|
75
|
+
"duodecillion" => 39,
|
76
|
+
"tredecillion" => 42,
|
77
|
+
"quattuordecillion" => 45,
|
78
|
+
"quindecillion" => 48,
|
79
|
+
"sexdecillion" => 51,
|
80
|
+
"septendecillion" => 54,
|
81
|
+
"octodecillion" => 57,
|
82
|
+
"novemdecillion" => 60,
|
83
|
+
"vigintillion" => 63,
|
84
|
+
"unvigintillion" => 66,
|
85
|
+
"duovigintillion" => 69,
|
86
|
+
"trevigintillion" => 72,
|
87
|
+
"quattuorvigintillion" => 75,
|
88
|
+
"quinvigintillion" => 78,
|
89
|
+
"sexvigintillion" => 81,
|
90
|
+
"septenvigintillion" => 84,
|
91
|
+
"octovigintillion" => 87,
|
92
|
+
"novemvigintillion" => 90,
|
93
|
+
"trigintillion" => 93,
|
94
|
+
"untrigintillion" => 96,
|
95
|
+
"duotrigintillion" => 99,
|
96
|
+
"googol" => 100
|
97
|
+
}
|
98
|
+
|
99
|
+
def strip_punctuation text
|
100
|
+
text = text.downcase.gsub /[^a-z ]/, " "
|
101
|
+
to_remove = true
|
102
|
+
|
103
|
+
to_remove = text.gsub! " ", " " while to_remove
|
104
|
+
|
105
|
+
text
|
106
|
+
end
|
111
107
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
108
|
+
def decimal_portion text
|
109
|
+
words = text.split " "
|
110
|
+
integers = word_array_to_integers words
|
111
|
+
decimal = "0." + integers.join()
|
112
|
+
decimal.to_f
|
113
|
+
end
|
116
114
|
|
117
115
|
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
memory
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
116
|
+
private
|
117
|
+
|
118
|
+
# Example: 364,895,457,898
|
119
|
+
#three hundred and sixty four billion eight hundred and ninety five million
|
120
|
+
#four hundred and fifty seven thousand eight hundred and ninety eight
|
121
|
+
#
|
122
|
+
#3 100 60 4 10^9, 8 100 90 5 10^6, 4 100 50 7 1000, 8 100 90 8
|
123
|
+
# memory answer
|
124
|
+
#x1. 3 add to memory because answer and memory are zero 3 0
|
125
|
+
#x2. memory * 100 (because memory<100) 300 0
|
126
|
+
#x3. 60 add to memory because memory > 60 360 0
|
127
|
+
#x3. 4 add to memory because memory > 4 364 0
|
128
|
+
#x4. multiply memory by 10^9 because memory < power of ten 364*10^9 0
|
129
|
+
#x5. add memory to answer (and reset)memory > 8 (memory pow of ten > 2) 0 364*10^9
|
130
|
+
#x6. 8 add to memory because not finished 8 ''
|
131
|
+
#x7. multiply memory by 100 because memory < 100 800 ''
|
132
|
+
#x8. add 90 to memory because memory > 90 890 ''
|
133
|
+
#x9. add 5 to memory because memory > 5 895 ''
|
134
|
+
#x10. multiply memory by 10^6 because memory < power of ten 895*10^6 ''
|
135
|
+
#x11. add memory to answer (and reset) because memory power ten > 2 0 364895 * 10^6
|
136
|
+
#x12. 4 add to memory because not finished 4 ''
|
137
|
+
#x13. memory * 100 because memory < 100 400 ''
|
138
|
+
#x14. memory + 50 because memory > 50 450 ''
|
139
|
+
#x15. memory + 7 because memory > 7 457 ''
|
140
|
+
#x16. memory * 1000 because memory < 1000 457000 ''
|
141
|
+
#x17. add memory to answer (and reset)memory > 8 (memory pow of ten > 2) 0 364895457000
|
142
|
+
#x18. 8 add to memory because not finished 8 ''
|
143
|
+
#x19. memory * 100 because memory < 100 800 ''
|
144
|
+
#x14. memory + 90 because memory > 90 890 ''
|
145
|
+
#x15. memory + 8 because memory > 8 898 ''
|
146
|
+
#16. finished so add memory to answer
|
147
|
+
|
148
|
+
#Example
|
149
|
+
#2001
|
150
|
+
#two thousand and one
|
151
|
+
#2 1000 1
|
152
|
+
# memory answer
|
153
|
+
#1. add 2 to memory because first 2 0
|
154
|
+
#2. multiply memory by 1000 because memory < 1000 2000 0
|
155
|
+
#3. add memory to answer,reset, because power of ten>2 0 2000
|
156
|
+
#4. add 1 to memory 1 2000
|
157
|
+
#5. finish - add memory to answer 0 2001
|
158
|
+
def parse_numbers(integers)
|
159
|
+
memory = 0
|
160
|
+
answer = 0
|
161
|
+
reset = true #reset each time memory is reset
|
162
|
+
integers.each_with_index do |integer, index|
|
163
|
+
if reset
|
164
|
+
reset = false
|
165
|
+
memory += integer
|
166
|
+
else
|
167
|
+
#x4. multiply memory by 10^9 because memory < power of ten
|
168
|
+
if is_power_of_ten?(integer)
|
169
|
+
if power_of_ten(integer)> 2
|
170
|
+
memory *= integer
|
171
|
+
#17. add memory to answer (and reset) (memory pow of ten > 2)
|
172
|
+
answer += memory
|
173
|
+
memory = 0
|
174
|
+
reset = true
|
175
|
+
end
|
175
176
|
end
|
176
|
-
end
|
177
177
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
178
|
+
if memory < integer
|
179
|
+
memory *= integer
|
180
|
+
else
|
181
|
+
memory += integer
|
182
|
+
end
|
182
183
|
end
|
183
184
|
end
|
185
|
+
answer += memory
|
184
186
|
end
|
185
|
-
answer += memory
|
186
|
-
end
|
187
187
|
|
188
|
-
|
189
|
-
|
190
|
-
|
188
|
+
def power_of_ten integer
|
189
|
+
Math.log10(integer)
|
190
|
+
end
|
191
191
|
|
192
|
-
|
193
|
-
|
194
|
-
|
192
|
+
def is_power_of_ten? integer
|
193
|
+
power_of_ten(integer)==power_of_ten(integer).to_i
|
194
|
+
end
|
195
195
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
end
|
196
|
+
#handles simple single word numbers
|
197
|
+
#e.g. one, seven, twenty, eight, thousand etc
|
198
|
+
def word_to_integer word
|
199
|
+
text = word.to_s.chomp.strip
|
200
|
+
#digits 0-9
|
201
|
+
digit = DIGITS.index(text)
|
202
|
+
return digit unless digit.nil?
|
203
|
+
|
204
|
+
#digits which are exceptions
|
205
|
+
exception = EXCEPTIONS[text]
|
206
|
+
return exception unless exception.nil?
|
207
|
+
|
208
|
+
power = POWERS_OF_TEN[text]
|
209
|
+
return 10**power unless power.nil?
|
210
|
+
end
|
212
211
|
|
213
|
-
|
214
|
-
|
215
|
-
words.map do |i|
|
216
|
-
word = word_to_integer(i)
|
217
|
-
out << word unless word.nil?
|
212
|
+
def word_array_to_integers words
|
213
|
+
words.map { |i| word_to_integer i }.compact
|
218
214
|
end
|
219
|
-
return out
|
220
215
|
end
|
221
216
|
end
|
222
217
|
|
data/numbers_in_words.gemspec
CHANGED
@@ -1,29 +1,28 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version = "0.1.
|
4
|
+
s.name = "numbers_in_words"
|
5
|
+
s.version = "0.1.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Mark Burns"]
|
9
|
-
s.date =
|
10
|
-
s.description =
|
11
|
-
s.email =
|
9
|
+
s.date = "2012-04-10"
|
10
|
+
s.description = "#in_words method for integers and #in_numbers for strings"
|
11
|
+
s.email = "markthedeveloper@gmail.com"
|
12
12
|
s.extra_rdoc_files = ["CHANGELOG", "README", "lib/numbers.rb", "lib/numbers_in_words.rb", "lib/words.rb"]
|
13
|
-
s.files = ["CHANGELOG", "Manifest", "README", "Rakefile", "examples/display_numbers_in_words.rb", "init.rb", "lib/numbers.rb", "lib/numbers_in_words.rb", "lib/words.rb", "
|
14
|
-
s.homepage =
|
13
|
+
s.files = ["CHANGELOG", "Manifest", "README", "Rakefile", "examples/display_numbers_in_words.rb", "init.rb", "lib/numbers.rb", "lib/numbers_in_words.rb", "lib/words.rb", "spec/numbers_in_words_spec.rb", "spec/words_in_numbers_spec.rb", "numbers_in_words.gemspec"]
|
14
|
+
s.homepage = "http://rubygems.org/gems/numbers_in_words"
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Numbers_in_words", "--main", "README"]
|
16
16
|
s.require_paths = ["lib"]
|
17
|
-
s.rubyforge_project =
|
18
|
-
s.rubygems_version =
|
19
|
-
s.summary =
|
17
|
+
s.rubyforge_project = "numbers_in_words"
|
18
|
+
s.rubygems_version = "1.8.17"
|
19
|
+
s.summary = "Example: 123.in_words #=> \"one hundred and twenty three\", \"seventy-five point eight\".in_numbers #=> 75.8"
|
20
20
|
|
21
21
|
if s.respond_to? :specification_version then
|
22
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
22
|
s.specification_version = 3
|
24
23
|
|
25
|
-
if Gem::Version.new(Gem::
|
26
|
-
s.
|
24
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
|
+
s.add_runtime_dependency(%q<active_support>, [">= 0"])
|
27
26
|
else
|
28
27
|
s.add_dependency(%q<active_support>, [">= 0"])
|
29
28
|
end
|