numbers_in_words 0.4.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +35 -1148
- data/.travis.yml +14 -4
- data/Gemfile +4 -1
- data/README.md +6 -44
- data/Rakefile +3 -1
- data/lib/numbers_in_words.rb +44 -19
- data/lib/numbers_in_words/duck_punch.rb +12 -8
- data/lib/numbers_in_words/exceptional_numbers.rb +115 -0
- data/lib/numbers_in_words/fraction.rb +136 -0
- data/lib/numbers_in_words/number_group.rb +34 -21
- data/lib/numbers_in_words/parsing/fraction_parsing.rb +34 -0
- data/lib/numbers_in_words/parsing/number_parser.rb +98 -0
- data/lib/numbers_in_words/parsing/pair_parsing.rb +64 -0
- data/lib/numbers_in_words/parsing/parse_fractions.rb +45 -0
- data/lib/numbers_in_words/parsing/parse_individual_number.rb +68 -0
- data/lib/numbers_in_words/parsing/parse_status.rb +17 -0
- data/lib/numbers_in_words/parsing/special.rb +67 -0
- data/lib/numbers_in_words/parsing/to_number.rb +77 -0
- data/lib/numbers_in_words/powers_of_ten.rb +49 -0
- data/lib/numbers_in_words/to_word.rb +78 -13
- data/lib/numbers_in_words/version.rb +3 -1
- data/lib/numbers_in_words/writer.rb +69 -0
- data/numbers_in_words.gemspec +14 -13
- data/spec/exceptional_numbers_spec.rb +26 -0
- data/spec/fraction_spec.rb +152 -0
- data/spec/fractions_spec.rb +31 -0
- data/spec/non_monkey_patch_spec.rb +39 -20
- data/spec/number_group_spec.rb +12 -12
- data/spec/number_parser_spec.rb +31 -0
- data/spec/numbers_in_words_spec.rb +63 -70
- data/spec/numerical_strings_spec.rb +28 -12
- data/spec/spec_helper.rb +23 -4
- data/spec/to_word_spec.rb +18 -0
- data/spec/words_in_numbers_spec.rb +132 -125
- data/spec/writer_spec.rb +26 -0
- data/spec/years_spec.rb +23 -13
- metadata +43 -27
- data/lib/numbers_in_words/english/constants.rb +0 -124
- data/lib/numbers_in_words/english/language_writer_english.rb +0 -116
- data/lib/numbers_in_words/language_writer.rb +0 -30
- data/lib/numbers_in_words/number_parser.rb +0 -135
- data/lib/numbers_in_words/to_number.rb +0 -88
- data/spec/language_writer_spec.rb +0 -23
@@ -1,30 +0,0 @@
|
|
1
|
-
module NumbersInWords
|
2
|
-
class LanguageWriter
|
3
|
-
attr_reader :that
|
4
|
-
delegate :exceptions, :powers_of_ten, to: :language
|
5
|
-
|
6
|
-
def initialize that
|
7
|
-
@that = that
|
8
|
-
end
|
9
|
-
|
10
|
-
def language
|
11
|
-
if @language.is_a? Module
|
12
|
-
@language
|
13
|
-
else
|
14
|
-
@language = NumbersInWords.const_get(@language)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def group_words size
|
19
|
-
#1000 and over Numbers are split into groups of three
|
20
|
-
groups = NumberGroup.groups_of @that, size
|
21
|
-
powers = groups.keys.sort.reverse #put in descending order
|
22
|
-
|
23
|
-
powers.each do |power|
|
24
|
-
name = powers_of_ten[power]
|
25
|
-
digits = groups[power]
|
26
|
-
yield power, name, digits
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
module NumbersInWords::NumberParser
|
2
|
-
SCALES_N = [100, 1000, 1000000, 1000000000, 1000000000000, 10**100]
|
3
|
-
# Example: 364,895,457,898
|
4
|
-
#three hundred and sixty four billion eight hundred and ninety five million
|
5
|
-
#four hundred and fifty seven thousand eight hundred and ninety eight
|
6
|
-
#
|
7
|
-
#3 100 60 4 10^9, 8 100 90 5 10^6, 4 100 50 7 1000, 8 100 90 8
|
8
|
-
# memory answer
|
9
|
-
#x1. 3 add to memory because answer and memory are zero 3 0
|
10
|
-
#x2. memory * 100 (because memory<100) 300 0
|
11
|
-
#x3. 60 add to memory because memory > 60 360 0
|
12
|
-
#x3. 4 add to memory because memory > 4 364 0
|
13
|
-
#x4. multiply memory by 10^9 because memory < power of ten 364*10^9 0
|
14
|
-
#x5. add memory to answer (and reset)memory > 8 (memory pow of ten > 2) 0 364*10^9
|
15
|
-
#x6. 8 add to memory because not finished 8 ''
|
16
|
-
#x7. multiply memory by 100 because memory < 100 800 ''
|
17
|
-
#x8. add 90 to memory because memory > 90 890 ''
|
18
|
-
#x9. add 5 to memory because memory > 5 895 ''
|
19
|
-
#x10. multiply memory by 10^6 because memory < power of ten 895*10^6 ''
|
20
|
-
#x11. add memory to answer (and reset) because memory power ten > 2 0 364895 * 10^6
|
21
|
-
#x12. 4 add to memory because not finished 4 ''
|
22
|
-
#x13. memory * 100 because memory < 100 400 ''
|
23
|
-
#x14. memory + 50 because memory > 50 450 ''
|
24
|
-
#x15. memory + 7 because memory > 7 457 ''
|
25
|
-
#x16. memory * 1000 because memory < 1000 457000 ''
|
26
|
-
#x17. add memory to answer (and reset)memory > 8 (memory pow of ten > 2) 0 364895457000
|
27
|
-
#x18. 8 add to memory because not finished 8 ''
|
28
|
-
#x19. memory * 100 because memory < 100 800 ''
|
29
|
-
#x14. memory + 90 because memory > 90 890 ''
|
30
|
-
#x15. memory + 8 because memory > 8 898 ''
|
31
|
-
#16. finished so add memory to answer
|
32
|
-
|
33
|
-
#Example
|
34
|
-
#2001
|
35
|
-
#two thousand and one
|
36
|
-
#2 1000 1
|
37
|
-
# memory answer
|
38
|
-
#1. add 2 to memory because first 2 0
|
39
|
-
#2. multiply memory by 1000 because memory < 1000 2000 0
|
40
|
-
#3. add memory to answer,reset, because power of ten>2 0 2000
|
41
|
-
#4. add 1 to memory 1 2000
|
42
|
-
#5. finish - add memory to answer 0 2001
|
43
|
-
def parse_ints(integers)
|
44
|
-
memory = 0
|
45
|
-
answer = 0
|
46
|
-
reset = true #reset each time memory is reset
|
47
|
-
integers.each do |integer|
|
48
|
-
if reset
|
49
|
-
reset = false
|
50
|
-
memory += integer
|
51
|
-
else
|
52
|
-
#x4. multiply memory by 10^9 because memory < power of ten
|
53
|
-
if power_of_ten?(integer)
|
54
|
-
if power_of_ten(integer)> 2
|
55
|
-
memory *= integer
|
56
|
-
#17. add memory to answer (and reset) (memory pow of ten > 2)
|
57
|
-
answer += memory
|
58
|
-
memory = 0
|
59
|
-
reset = true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
if memory < integer
|
63
|
-
memory *= integer
|
64
|
-
else
|
65
|
-
memory += integer
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
answer += memory
|
70
|
-
end
|
71
|
-
|
72
|
-
def parse(integers, only_compress = false)
|
73
|
-
if integers.length < 2
|
74
|
-
return integers if only_compress
|
75
|
-
return integers.empty? ? 0 : integers[0]
|
76
|
-
end
|
77
|
-
if [] == (SCALES_N & integers)
|
78
|
-
return pair_parse(integers, only_compress)
|
79
|
-
end
|
80
|
-
|
81
|
-
parse_ints(integers)
|
82
|
-
end
|
83
|
-
|
84
|
-
def power_of_ten integer
|
85
|
-
Math.log10(integer)
|
86
|
-
end
|
87
|
-
|
88
|
-
def power_of_ten? integer
|
89
|
-
power_of_ten(integer) == power_of_ten(integer).to_i
|
90
|
-
end
|
91
|
-
|
92
|
-
# 15,16
|
93
|
-
# 85,16
|
94
|
-
def pair_parse(ints, only_compress = false)
|
95
|
-
ints = compress(ints)
|
96
|
-
return ints if only_compress
|
97
|
-
return ints[0] if ints.length == 1
|
98
|
-
sum = 0
|
99
|
-
ints.each do |n|
|
100
|
-
sum *= n >= 10 ? 100 : 10
|
101
|
-
sum += n
|
102
|
-
end
|
103
|
-
sum
|
104
|
-
end
|
105
|
-
|
106
|
-
# [40, 2] => [42]
|
107
|
-
def compress(ints)
|
108
|
-
res = []
|
109
|
-
i = 0
|
110
|
-
return [] if ints.empty?
|
111
|
-
while i < ints.length - 1
|
112
|
-
int, jump = compress_int(ints[i], ints[i + 1])
|
113
|
-
res << int
|
114
|
-
i += jump
|
115
|
-
end
|
116
|
-
if i < ints.length
|
117
|
-
res << ints[-1]
|
118
|
-
else
|
119
|
-
res
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def compress_int(int, sequel)
|
124
|
-
tens = int % 10 == 0 && int > 10
|
125
|
-
if tens && sequel < 10
|
126
|
-
return [int + sequel, 2]
|
127
|
-
else
|
128
|
-
return [int, 1]
|
129
|
-
end
|
130
|
-
|
131
|
-
[res, jump]
|
132
|
-
end
|
133
|
-
|
134
|
-
extend self
|
135
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
class NumbersInWords::ToNumber
|
2
|
-
delegate :to_s, to: :that
|
3
|
-
delegate :powers_of_ten_to_i, :exceptions_to_i, :canonize, \
|
4
|
-
:check_mixed, :check_one, :strip_minus, :check_decimal, to: :language
|
5
|
-
attr_reader :that, :language
|
6
|
-
|
7
|
-
def initialize that, language=NumbersInWords.language
|
8
|
-
@that = that
|
9
|
-
@language = language
|
10
|
-
end
|
11
|
-
|
12
|
-
def language
|
13
|
-
if @language.is_a? Module
|
14
|
-
@language
|
15
|
-
else
|
16
|
-
@language = NumbersInWords.const_get(@language)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def handle_negative(text, only_compress)
|
21
|
-
stripped = strip_minus text
|
22
|
-
if stripped
|
23
|
-
stripped_n = NumbersInWords.in_numbers(stripped, language, only_compress)
|
24
|
-
only_compress ? stripped_n.map{ |k| k * -1 } : -1 * stripped_n
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def in_numbers(only_compress = false)
|
29
|
-
text = to_s.strip
|
30
|
-
return text.to_f if text =~ /^-?\d+(.\d+)?$/
|
31
|
-
|
32
|
-
text = strip_punctuation text
|
33
|
-
|
34
|
-
i = handle_negative(text, only_compress)
|
35
|
-
return i if i
|
36
|
-
|
37
|
-
mixed = check_mixed text
|
38
|
-
return mixed if mixed
|
39
|
-
|
40
|
-
one = check_one text
|
41
|
-
if one
|
42
|
-
res = NumbersInWords.in_numbers(one[1], language)
|
43
|
-
return only_compress ? [res] : res
|
44
|
-
end
|
45
|
-
|
46
|
-
h = handle_decimals text
|
47
|
-
return h if h
|
48
|
-
|
49
|
-
integers = word_array_to_integers text.split(" ")
|
50
|
-
|
51
|
-
NumbersInWords::NumberParser.parse integers, only_compress
|
52
|
-
end
|
53
|
-
|
54
|
-
def strip_punctuation text
|
55
|
-
text = text.downcase.gsub(/[^a-z 0-9]/, " ")
|
56
|
-
to_remove = true
|
57
|
-
|
58
|
-
to_remove = text.gsub! " ", " " while to_remove
|
59
|
-
|
60
|
-
text
|
61
|
-
end
|
62
|
-
|
63
|
-
def handle_decimals text
|
64
|
-
match = check_decimal text
|
65
|
-
if match
|
66
|
-
integer = NumbersInWords.in_numbers(match.pre_match)
|
67
|
-
decimal = NumbersInWords.in_numbers(match.post_match)
|
68
|
-
integer += "0.#{decimal}".to_f
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
#handles simple single word numbers
|
73
|
-
#e.g. one, seven, twenty, eight, thousand etc
|
74
|
-
def word_to_integer word
|
75
|
-
text = canonize(word.to_s.chomp.strip)
|
76
|
-
|
77
|
-
exception = exceptions_to_i[text]
|
78
|
-
return exception if exception
|
79
|
-
|
80
|
-
power = powers_of_ten_to_i[text]
|
81
|
-
return 10 ** power if power
|
82
|
-
end
|
83
|
-
|
84
|
-
def word_array_to_integers words
|
85
|
-
words.map { |i| word_to_integer i }.compact
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require './spec/spec_helper'
|
2
|
-
|
3
|
-
describe NumbersInWords::English::LanguageWriterEnglish do
|
4
|
-
it "should display numbers grouped" do
|
5
|
-
count = 0
|
6
|
-
@writer = NumbersInWords::English::LanguageWriterEnglish.new(2111)
|
7
|
-
@writer.group_words(3) do |power, name, digits|
|
8
|
-
case count
|
9
|
-
when 0
|
10
|
-
expect(power).to eq(3)
|
11
|
-
expect(name).to eq("thousand")
|
12
|
-
expect(digits).to eq(2)
|
13
|
-
when 1
|
14
|
-
expect(power).to eq(0)
|
15
|
-
expect(name).to eq("one")
|
16
|
-
expect(digits).to eq(111)
|
17
|
-
end
|
18
|
-
count += 1
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
|