numbers_in_words 0.4.0 → 1.0.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.
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