numbers_in_words 0.4.0 → 0.4.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 (44) 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 +4 -4
  6. data/Gemfile +3 -1
  7. data/README.md +5 -43
  8. data/Rakefile +3 -1
  9. data/lib/numbers_in_words.rb +43 -19
  10. data/lib/numbers_in_words/duck_punch.rb +12 -8
  11. data/lib/numbers_in_words/exceptional_numbers.rb +119 -0
  12. data/lib/numbers_in_words/fraction.rb +151 -0
  13. data/lib/numbers_in_words/number_group.rb +34 -21
  14. data/lib/numbers_in_words/parsing/number_parser.rb +98 -0
  15. data/lib/numbers_in_words/parsing/pair_parsing.rb +64 -0
  16. data/lib/numbers_in_words/parsing/parse_fractions.rb +45 -0
  17. data/lib/numbers_in_words/parsing/parse_individual_number.rb +68 -0
  18. data/lib/numbers_in_words/parsing/parse_status.rb +17 -0
  19. data/lib/numbers_in_words/parsing/to_number.rb +159 -0
  20. data/lib/numbers_in_words/powers_of_ten.rb +49 -0
  21. data/lib/numbers_in_words/to_word.rb +78 -13
  22. data/lib/numbers_in_words/version.rb +3 -1
  23. data/lib/numbers_in_words/writer.rb +69 -0
  24. data/numbers_in_words.gemspec +14 -13
  25. data/spec/exceptional_numbers_spec.rb +26 -0
  26. data/spec/fraction_spec.rb +132 -0
  27. data/spec/fractions_spec.rb +31 -0
  28. data/spec/non_monkey_patch_spec.rb +39 -20
  29. data/spec/number_group_spec.rb +12 -12
  30. data/spec/number_parser_spec.rb +63 -0
  31. data/spec/numbers_in_words_spec.rb +56 -69
  32. data/spec/numerical_strings_spec.rb +28 -12
  33. data/spec/spec_helper.rb +2 -4
  34. data/spec/to_word_spec.rb +18 -0
  35. data/spec/words_in_numbers_spec.rb +130 -125
  36. data/spec/writer_spec.rb +26 -0
  37. data/spec/years_spec.rb +23 -13
  38. metadata +40 -25
  39. data/lib/numbers_in_words/english/constants.rb +0 -124
  40. data/lib/numbers_in_words/english/language_writer_english.rb +0 -116
  41. data/lib/numbers_in_words/language_writer.rb +0 -30
  42. data/lib/numbers_in_words/number_parser.rb +0 -135
  43. data/lib/numbers_in_words/to_number.rb +0 -88
  44. 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: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
@@ -9,37 +9,37 @@ 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-08-06 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
@@ -54,28 +54,39 @@ files:
54
54
  - ".rubocop.yml"
55
55
  - ".travis.yml"
56
56
  - Gemfile
57
+ - Gemfile.lock
57
58
  - LICENSE.txt
58
59
  - README.md
59
60
  - Rakefile
60
61
  - bin/spec
61
62
  - lib/numbers_in_words.rb
62
63
  - 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
64
+ - lib/numbers_in_words/exceptional_numbers.rb
65
+ - lib/numbers_in_words/fraction.rb
66
66
  - lib/numbers_in_words/number_group.rb
67
- - lib/numbers_in_words/number_parser.rb
68
- - lib/numbers_in_words/to_number.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/to_number.rb
73
+ - lib/numbers_in_words/powers_of_ten.rb
69
74
  - lib/numbers_in_words/to_word.rb
70
75
  - lib/numbers_in_words/version.rb
76
+ - lib/numbers_in_words/writer.rb
71
77
  - numbers_in_words.gemspec
72
- - spec/language_writer_spec.rb
78
+ - spec/exceptional_numbers_spec.rb
79
+ - spec/fraction_spec.rb
80
+ - spec/fractions_spec.rb
73
81
  - spec/non_monkey_patch_spec.rb
74
82
  - spec/number_group_spec.rb
83
+ - spec/number_parser_spec.rb
75
84
  - spec/numbers_in_words_spec.rb
76
85
  - spec/numerical_strings_spec.rb
77
86
  - spec/spec_helper.rb
87
+ - spec/to_word_spec.rb
78
88
  - spec/words_in_numbers_spec.rb
89
+ - spec/writer_spec.rb
79
90
  - spec/years_spec.rb
80
91
  homepage: http://github.com/markburns/numbers_in_words
81
92
  licenses: []
@@ -95,18 +106,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
106
  - !ruby/object:Gem::Version
96
107
  version: '0'
97
108
  requirements: []
98
- rubyforge_project:
99
- rubygems_version: 2.4.5
109
+ rubygems_version: 3.0.3
100
110
  signing_key:
101
111
  specification_version: 4
102
- summary: 'Example: 123.in_words # => "one hundred and twenty three", "seventy-five
103
- point eight".in_numbers # = > 75.8'
112
+ summary: 'Example: NumbersInWords.in_words(123) # => "one hundred and twenty three",
113
+ NumbersInWords.in_numbers("seventy-five point eight") # = > 75.8'
104
114
  test_files:
105
- - spec/language_writer_spec.rb
115
+ - spec/exceptional_numbers_spec.rb
116
+ - spec/fraction_spec.rb
117
+ - spec/fractions_spec.rb
106
118
  - spec/non_monkey_patch_spec.rb
107
119
  - spec/number_group_spec.rb
120
+ - spec/number_parser_spec.rb
108
121
  - spec/numbers_in_words_spec.rb
109
122
  - spec/numerical_strings_spec.rb
110
123
  - spec/spec_helper.rb
124
+ - spec/to_word_spec.rb
111
125
  - spec/words_in_numbers_spec.rb
126
+ - spec/writer_spec.rb
112
127
  - 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
@@ -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