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.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +35 -1148
  5. data/.travis.yml +14 -4
  6. data/Gemfile +4 -1
  7. data/README.md +6 -44
  8. data/Rakefile +3 -1
  9. data/lib/numbers_in_words.rb +44 -19
  10. data/lib/numbers_in_words/duck_punch.rb +12 -8
  11. data/lib/numbers_in_words/exceptional_numbers.rb +115 -0
  12. data/lib/numbers_in_words/fraction.rb +136 -0
  13. data/lib/numbers_in_words/number_group.rb +34 -21
  14. data/lib/numbers_in_words/parsing/fraction_parsing.rb +34 -0
  15. data/lib/numbers_in_words/parsing/number_parser.rb +98 -0
  16. data/lib/numbers_in_words/parsing/pair_parsing.rb +64 -0
  17. data/lib/numbers_in_words/parsing/parse_fractions.rb +45 -0
  18. data/lib/numbers_in_words/parsing/parse_individual_number.rb +68 -0
  19. data/lib/numbers_in_words/parsing/parse_status.rb +17 -0
  20. data/lib/numbers_in_words/parsing/special.rb +67 -0
  21. data/lib/numbers_in_words/parsing/to_number.rb +77 -0
  22. data/lib/numbers_in_words/powers_of_ten.rb +49 -0
  23. data/lib/numbers_in_words/to_word.rb +78 -13
  24. data/lib/numbers_in_words/version.rb +3 -1
  25. data/lib/numbers_in_words/writer.rb +69 -0
  26. data/numbers_in_words.gemspec +14 -13
  27. data/spec/exceptional_numbers_spec.rb +26 -0
  28. data/spec/fraction_spec.rb +152 -0
  29. data/spec/fractions_spec.rb +31 -0
  30. data/spec/non_monkey_patch_spec.rb +39 -20
  31. data/spec/number_group_spec.rb +12 -12
  32. data/spec/number_parser_spec.rb +31 -0
  33. data/spec/numbers_in_words_spec.rb +63 -70
  34. data/spec/numerical_strings_spec.rb +28 -12
  35. data/spec/spec_helper.rb +23 -4
  36. data/spec/to_word_spec.rb +18 -0
  37. data/spec/words_in_numbers_spec.rb +132 -125
  38. data/spec/writer_spec.rb +26 -0
  39. data/spec/years_spec.rb +23 -13
  40. metadata +43 -27
  41. data/lib/numbers_in_words/english/constants.rb +0 -124
  42. data/lib/numbers_in_words/english/language_writer_english.rb +0 -116
  43. data/lib/numbers_in_words/language_writer.rb +0 -30
  44. data/lib/numbers_in_words/number_parser.rb +0 -135
  45. data/lib/numbers_in_words/to_number.rb +0 -88
  46. data/spec/language_writer_spec.rb +0 -23
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe NumbersInWords::Writer do
4
+ let(:number) { 2_111 }
5
+ let(:writer) { described_class.new(number) }
6
+
7
+ it 'should display numbers grouped' do
8
+ count = 0
9
+
10
+ writer.group_words(3) do |power, name, digits|
11
+ case count
12
+ when 0
13
+ expect(power).to eq(3)
14
+ expect(name).to eq('thousand')
15
+ expect(digits).to eq(2)
16
+ when 1
17
+ expect(power).to eq(0)
18
+ expect(name).to eq('one')
19
+ expect(digits).to eq(111)
20
+ end
21
+ count += 1
22
+ end
23
+
24
+ expect(count).to eq 2
25
+ end
26
+ end
@@ -1,17 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require './spec/spec_helper'
2
4
 
3
- describe WordsInNumbers do
4
- it "should handle years notation" do
5
- expect("fifteen sixteen seventeen".in_numbers).to eq(151617)
6
- expect("forty nine ninety eight forty seven seventy nine".in_numbers).to eq(49984779)
7
- expect("sixty seven six".in_numbers) .to eq(676)
8
- expect("one fifty".in_numbers).to eq(150)
9
- expect("two fifty".in_numbers).to eq(250)
10
- expect("one point fifty six fifty seven".in_numbers).to eq(1.5657)
11
- expect("one three forty seven".in_numbers).to eq(1347)
12
- expect("one three five point forty seven".in_numbers).to eq(135.47)
13
- expect("one ten sixty three".in_numbers).to eq(11063)
14
- expect("one nineteen ten oh five".in_numbers).to eq(1191005)
15
- end
5
+ describe NumbersInWords::NumericExtension do
6
+ YEARS = {
7
+ 'thirteen hundred' => 13_00,
8
+ 'twenty-two hundred' => 22_00,
9
+ 'twenty-two hundred and five' => 22_05,
10
+ 'fifteen sixteen seventeen' => 151_617,
11
+ 'forty-nine ninety-eight forty-seven seventy-nine' => 49_984_779,
12
+ 'one fifty' => 150,
13
+ 'two fifty' => 250,
14
+ 'three fifty' => 350,
15
+ 'one point fifty-six fifty-seven' => 1.5657,
16
+ 'one three forty-seven' => 1347,
17
+ 'one three five-point forty-seven' => 135.47,
18
+ 'one ten sixty-three' => 11_063,
19
+ 'one nineteen ten oh five' => 1_191_005
20
+ }.freeze
16
21
 
22
+ YEARS.each do |k, v|
23
+ it do
24
+ expect(k.in_numbers).to eql(v)
25
+ end
26
+ end
17
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numbers_in_words
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
@@ -9,42 +9,41 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-02 00:00:00.000000000 Z
12
+ date: 2020-11-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: activesupport
15
+ name: rspec
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :runtime
20
+ version: 3.4.0
21
+ type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '0'
27
+ version: 3.4.0
28
28
  - !ruby/object:Gem::Dependency
29
- name: rspec
29
+ name: rubocop
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 3.4.0
34
+ version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 3.4.0
42
- description: "#in_words method for integers and #in_numbers for strings"
41
+ version: '0'
42
+ description: convert written numbers into Integers and vice-versa
43
43
  email:
44
44
  - markthedeveloper@gmail.com
45
45
  - dimidd@gmail.com
46
- executables:
47
- - spec
46
+ executables: []
48
47
  extensions: []
49
48
  extra_rdoc_files: []
50
49
  files:
@@ -54,28 +53,41 @@ files:
54
53
  - ".rubocop.yml"
55
54
  - ".travis.yml"
56
55
  - Gemfile
56
+ - Gemfile.lock
57
57
  - LICENSE.txt
58
58
  - README.md
59
59
  - Rakefile
60
60
  - bin/spec
61
61
  - lib/numbers_in_words.rb
62
62
  - lib/numbers_in_words/duck_punch.rb
63
- - lib/numbers_in_words/english/constants.rb
64
- - lib/numbers_in_words/english/language_writer_english.rb
65
- - lib/numbers_in_words/language_writer.rb
63
+ - lib/numbers_in_words/exceptional_numbers.rb
64
+ - lib/numbers_in_words/fraction.rb
66
65
  - lib/numbers_in_words/number_group.rb
67
- - lib/numbers_in_words/number_parser.rb
68
- - lib/numbers_in_words/to_number.rb
66
+ - lib/numbers_in_words/parsing/fraction_parsing.rb
67
+ - lib/numbers_in_words/parsing/number_parser.rb
68
+ - lib/numbers_in_words/parsing/pair_parsing.rb
69
+ - lib/numbers_in_words/parsing/parse_fractions.rb
70
+ - lib/numbers_in_words/parsing/parse_individual_number.rb
71
+ - lib/numbers_in_words/parsing/parse_status.rb
72
+ - lib/numbers_in_words/parsing/special.rb
73
+ - lib/numbers_in_words/parsing/to_number.rb
74
+ - lib/numbers_in_words/powers_of_ten.rb
69
75
  - lib/numbers_in_words/to_word.rb
70
76
  - lib/numbers_in_words/version.rb
77
+ - lib/numbers_in_words/writer.rb
71
78
  - numbers_in_words.gemspec
72
- - spec/language_writer_spec.rb
79
+ - spec/exceptional_numbers_spec.rb
80
+ - spec/fraction_spec.rb
81
+ - spec/fractions_spec.rb
73
82
  - spec/non_monkey_patch_spec.rb
74
83
  - spec/number_group_spec.rb
84
+ - spec/number_parser_spec.rb
75
85
  - spec/numbers_in_words_spec.rb
76
86
  - spec/numerical_strings_spec.rb
77
87
  - spec/spec_helper.rb
88
+ - spec/to_word_spec.rb
78
89
  - spec/words_in_numbers_spec.rb
90
+ - spec/writer_spec.rb
79
91
  - spec/years_spec.rb
80
92
  homepage: http://github.com/markburns/numbers_in_words
81
93
  licenses: []
@@ -95,18 +107,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
107
  - !ruby/object:Gem::Version
96
108
  version: '0'
97
109
  requirements: []
98
- rubyforge_project:
99
- rubygems_version: 2.4.5
110
+ rubygems_version: 3.0.3
100
111
  signing_key:
101
112
  specification_version: 4
102
- summary: 'Example: 123.in_words # => "one hundred and twenty three", "seventy-five
103
- point eight".in_numbers # = > 75.8'
113
+ summary: 'Example: NumbersInWords.in_words(123) # => "one hundred and twenty three",
114
+ NumbersInWords.in_numbers("seventy-five point eight") # = > 75.8'
104
115
  test_files:
105
- - spec/language_writer_spec.rb
116
+ - spec/exceptional_numbers_spec.rb
117
+ - spec/fraction_spec.rb
118
+ - spec/fractions_spec.rb
106
119
  - spec/non_monkey_patch_spec.rb
107
120
  - spec/number_group_spec.rb
121
+ - spec/number_parser_spec.rb
108
122
  - spec/numbers_in_words_spec.rb
109
123
  - spec/numerical_strings_spec.rb
110
124
  - spec/spec_helper.rb
125
+ - spec/to_word_spec.rb
111
126
  - spec/words_in_numbers_spec.rb
127
+ - spec/writer_spec.rb
112
128
  - spec/years_spec.rb
@@ -1,124 +0,0 @@
1
- module NumbersInWords
2
- module English
3
-
4
- def self.canonize(w)
5
- aliases = {
6
- "oh" => "zero"
7
- }
8
- canon = aliases[w]
9
- return canon ? canon : w
10
- end
11
-
12
- def self.exceptions
13
- {
14
- 0 => "zero",
15
- 1 => "one",
16
- 2 => "two",
17
- 3 => "three",
18
- 4 => "four",
19
- 5 => "five",
20
- 6 => "six",
21
- 7 => "seven",
22
- 8 => "eight",
23
- 9 => "nine",
24
-
25
- 10 => "ten",
26
- 11 => "eleven",
27
- 12 => "twelve",
28
-
29
- 13 => "thirteen",
30
- 14 => "fourteen",
31
- 15 => "fifteen",
32
- 16 => "sixteen" ,
33
- 17 => "seventeen",
34
- 18 => "eighteen",
35
- 19 => "nineteen",
36
-
37
- 20 => "twenty",
38
- 30 => "thirty",
39
- 40 => "forty",
40
- 50 => "fifty",
41
- 60 => "sixty",
42
- 70 => "seventy",
43
- 80 => "eighty",
44
- 90 => "ninety"
45
- }
46
- end
47
-
48
- def self.swap_keys hsh
49
- hsh.inject({}){|h,(k,v)| h[v]=k; h}
50
- end
51
-
52
- def self.powers_of_ten
53
- {
54
- 0 => "one",
55
- 1 => "ten",
56
- 2 => "hundred",
57
- 3 => "thousand",
58
- 6 => "million",
59
- 9 => "billion",
60
- 12 => "trillion",
61
- 15 => "quadrillion",
62
- 18 => "quintillion",
63
- 21 => "sextillion",
64
- 24 => "septillion",
65
- 27 => "octillion",
66
- 30 => "nonillion",
67
- 33 => "decillion",
68
- 36 => "undecillion",
69
- 39 => "duodecillion",
70
- 42 => "tredecillion",
71
- 45 => "quattuordecillion",
72
- 48 => "quindecillion",
73
- 51 => "sexdecillion",
74
- 54 => "septendecillion",
75
- 57 => "octodecillion",
76
- 60 => "novemdecillion",
77
- 63 => "vigintillion",
78
- 66 => "unvigintillion",
79
- 69 => "duovigintillion",
80
- 72 => "trevigintillion",
81
- 75 => "quattuorvigintillion",
82
- 78 => "quinvigintillion",
83
- 81 => "sexvigintillion",
84
- 84 => "septenvigintillion",
85
- 87 => "octovigintillion",
86
- 90 => "novemvigintillion",
87
- 93 => "trigintillion",
88
- 96 => "untrigintillion",
89
- 99 => "duotrigintillion",
90
- 100 => "googol"
91
- }
92
- end
93
-
94
- def self.exceptions_to_i
95
- swap_keys exceptions
96
- end
97
-
98
- def self.powers_of_ten_to_i
99
- swap_keys powers_of_ten
100
- end
101
-
102
- POWERS_RX = Regexp.union(powers_of_ten.values[1..-1])
103
-
104
- def self.check_mixed(txt)
105
- mixed = txt.match /^(-?\d+(.\d+)?) (#{POWERS_RX}s?)$/
106
- if mixed && mixed[1] && mixed[3]
107
- matches = [mixed[1], mixed[3]].map{ |m| NumbersInWords.in_numbers m }
108
- return matches.reduce(&:*)
109
- end
110
- end
111
-
112
- def self.check_one(txt)
113
- one = txt.match /^one (#{POWERS_RX})$/
114
- end
115
-
116
- def self.strip_minus(txt)
117
- stripped = txt.gsub(/^minus/, "") if txt =~ /^minus/
118
- end
119
-
120
- def self.check_decimal(txt)
121
- txt.match(/\spoint\s/)
122
- end
123
- end
124
- end
@@ -1,116 +0,0 @@
1
- module NumbersInWords
2
- module English
3
- class LanguageWriterEnglish < LanguageWriter
4
- delegate :to_i, to: :that
5
-
6
- def initialize that
7
- super that
8
- @language = "English"
9
- end
10
-
11
- def negative
12
- "minus " + NumbersInWords.in_words(-@that)
13
- end
14
-
15
- def in_words
16
- v = handle_exception
17
- return v if v
18
-
19
- in_decimals = decimals
20
- return in_decimals if in_decimals
21
-
22
- number = to_i
23
-
24
- return negative() if number < 0
25
-
26
- output = if number.to_s.length == 2 #20-99
27
- handle_tens(number)
28
- else
29
- write() #longer numbers
30
- end
31
-
32
- output.strip
33
- end
34
-
35
- def handle_tens(number)
36
- output = ""
37
-
38
- tens = (number/10).round*10 #write the tens
39
-
40
- output << exceptions[tens] # e.g. eighty
41
-
42
- digit = number - tens #write the digits
43
-
44
- unless digit == 0
45
- output << " " + NumbersInWords.in_words(digit)
46
- end
47
-
48
- output
49
- end
50
-
51
- def handle_exception
52
- exceptions[@that] if @that.is_a?(Integer) and exceptions[@that]
53
- end
54
-
55
-
56
- def write
57
- length = @that.to_s.length
58
- output =
59
- if length == 3
60
- #e.g. 113 splits into "one hundred" and "thirteen"
61
- write_groups(2)
62
-
63
- #more than one hundred less than one googol
64
- elsif length < LENGTH_OF_GOOGOL
65
- write_groups(3)
66
-
67
- elsif length >= LENGTH_OF_GOOGOL
68
- write_googols
69
- end
70
- output.strip
71
- end
72
-
73
- def decimals
74
- int, decimals = NumberGroup.new(@that).split_decimals
75
- if int
76
- out = NumbersInWords.in_words(int) + " point "
77
- decimals.each do |decimal|
78
- out << NumbersInWords.in_words(decimal.to_i) + " "
79
- end
80
- out.strip
81
- end
82
- end
83
-
84
- private
85
-
86
- def write_googols
87
- googols, remainder = NumberGroup.new(@that).split_googols
88
- output = ""
89
-
90
- output << " " + NumbersInWords.in_words(googols) + " googol"
91
- if remainder > 0
92
- prefix = " "
93
- prefix << "and " if remainder < 100
94
- output << prefix + NumbersInWords.in_words(remainder)
95
- end
96
-
97
- output
98
- end
99
-
100
- def write_groups group
101
- #e.g. 113 splits into "one hundred" and "thirteen"
102
- output = ""
103
- group_words(group) do |power, name, digits|
104
- if digits > 0
105
- prefix = " "
106
- #no and between thousands and hundreds
107
- prefix << "and " if power == 0 and digits < 100
108
- output << prefix + NumbersInWords.in_words(digits)
109
- output << prefix + name unless power == 0
110
- end
111
- end
112
- output
113
- end
114
- end
115
- end
116
- end