numbers_in_words 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|