numbers_in_words 0.3.0 → 1.0.0

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 (48) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +2 -0
  3. data/.gitignore +1 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +35 -1148
  6. data/.travis.yml +14 -4
  7. data/Gemfile +4 -1
  8. data/README.md +6 -43
  9. data/Rakefile +3 -1
  10. data/bin/spec +0 -0
  11. data/lib/numbers_in_words.rb +44 -19
  12. data/lib/numbers_in_words/duck_punch.rb +12 -8
  13. data/lib/numbers_in_words/exceptional_numbers.rb +115 -0
  14. data/lib/numbers_in_words/fraction.rb +136 -0
  15. data/lib/numbers_in_words/number_group.rb +34 -25
  16. data/lib/numbers_in_words/parsing/fraction_parsing.rb +34 -0
  17. data/lib/numbers_in_words/parsing/number_parser.rb +98 -0
  18. data/lib/numbers_in_words/parsing/pair_parsing.rb +64 -0
  19. data/lib/numbers_in_words/parsing/parse_fractions.rb +45 -0
  20. data/lib/numbers_in_words/parsing/parse_individual_number.rb +68 -0
  21. data/lib/numbers_in_words/parsing/parse_status.rb +17 -0
  22. data/lib/numbers_in_words/parsing/special.rb +67 -0
  23. data/lib/numbers_in_words/parsing/to_number.rb +77 -0
  24. data/lib/numbers_in_words/powers_of_ten.rb +49 -0
  25. data/lib/numbers_in_words/to_word.rb +78 -13
  26. data/lib/numbers_in_words/version.rb +3 -1
  27. data/lib/numbers_in_words/writer.rb +69 -0
  28. data/numbers_in_words.gemspec +14 -13
  29. data/spec/exceptional_numbers_spec.rb +26 -0
  30. data/spec/fraction_spec.rb +152 -0
  31. data/spec/fractions_spec.rb +31 -0
  32. data/spec/non_monkey_patch_spec.rb +40 -15
  33. data/spec/number_group_spec.rb +12 -12
  34. data/spec/number_parser_spec.rb +31 -0
  35. data/spec/numbers_in_words_spec.rb +63 -70
  36. data/spec/numerical_strings_spec.rb +35 -0
  37. data/spec/spec_helper.rb +24 -4
  38. data/spec/to_word_spec.rb +18 -0
  39. data/spec/words_in_numbers_spec.rb +133 -116
  40. data/spec/writer_spec.rb +26 -0
  41. data/spec/years_spec.rb +27 -0
  42. metadata +49 -27
  43. data/lib/numbers_in_words/english/constants.rb +0 -93
  44. data/lib/numbers_in_words/english/language_writer_english.rb +0 -109
  45. data/lib/numbers_in_words/language_writer.rb +0 -31
  46. data/lib/numbers_in_words/number_parser.rb +0 -81
  47. data/lib/numbers_in_words/to_number.rb +0 -82
  48. 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
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './spec/spec_helper'
4
+
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
21
+
22
+ YEARS.each do |k, v|
23
+ it do
24
+ expect(k.in_numbers).to eql(v)
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,48 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numbers_in_words
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
8
+ - Dimid Duchovny
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-11-30 00:00:00.000000000 Z
12
+ date: 2020-11-29 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: activesupport
15
+ name: rspec
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ">="
18
+ - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
20
+ version: 3.4.0
21
+ type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - ">="
25
+ - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: '0'
27
+ version: 3.4.0
27
28
  - !ruby/object:Gem::Dependency
28
- name: rspec
29
+ name: rubocop
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: 3.4.0
34
+ version: '0'
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - "~>"
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
- version: 3.4.0
41
- description: "#in_words method for integers and #in_numbers for strings"
41
+ version: '0'
42
+ description: convert written numbers into Integers and vice-versa
42
43
  email:
43
44
  - markthedeveloper@gmail.com
44
- executables:
45
- - spec
45
+ - dimidd@gmail.com
46
+ executables: []
46
47
  extensions: []
47
48
  extra_rdoc_files: []
48
49
  files:
@@ -52,27 +53,42 @@ files:
52
53
  - ".rubocop.yml"
53
54
  - ".travis.yml"
54
55
  - Gemfile
56
+ - Gemfile.lock
55
57
  - LICENSE.txt
56
58
  - README.md
57
59
  - Rakefile
58
60
  - bin/spec
59
61
  - lib/numbers_in_words.rb
60
62
  - lib/numbers_in_words/duck_punch.rb
61
- - lib/numbers_in_words/english/constants.rb
62
- - lib/numbers_in_words/english/language_writer_english.rb
63
- - lib/numbers_in_words/language_writer.rb
63
+ - lib/numbers_in_words/exceptional_numbers.rb
64
+ - lib/numbers_in_words/fraction.rb
64
65
  - lib/numbers_in_words/number_group.rb
65
- - lib/numbers_in_words/number_parser.rb
66
- - 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
67
75
  - lib/numbers_in_words/to_word.rb
68
76
  - lib/numbers_in_words/version.rb
77
+ - lib/numbers_in_words/writer.rb
69
78
  - numbers_in_words.gemspec
70
- - spec/language_writer_spec.rb
79
+ - spec/exceptional_numbers_spec.rb
80
+ - spec/fraction_spec.rb
81
+ - spec/fractions_spec.rb
71
82
  - spec/non_monkey_patch_spec.rb
72
83
  - spec/number_group_spec.rb
84
+ - spec/number_parser_spec.rb
73
85
  - spec/numbers_in_words_spec.rb
86
+ - spec/numerical_strings_spec.rb
74
87
  - spec/spec_helper.rb
88
+ - spec/to_word_spec.rb
75
89
  - spec/words_in_numbers_spec.rb
90
+ - spec/writer_spec.rb
91
+ - spec/years_spec.rb
76
92
  homepage: http://github.com/markburns/numbers_in_words
77
93
  licenses: []
78
94
  metadata: {}
@@ -91,16 +107,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
107
  - !ruby/object:Gem::Version
92
108
  version: '0'
93
109
  requirements: []
94
- rubyforge_project:
95
- rubygems_version: 2.4.5
110
+ rubygems_version: 3.0.3
96
111
  signing_key:
97
112
  specification_version: 4
98
- summary: 'Example: 123.in_words # => "one hundred and twenty three", "seventy-five
99
- 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'
100
115
  test_files:
101
- - spec/language_writer_spec.rb
116
+ - spec/exceptional_numbers_spec.rb
117
+ - spec/fraction_spec.rb
118
+ - spec/fractions_spec.rb
102
119
  - spec/non_monkey_patch_spec.rb
103
120
  - spec/number_group_spec.rb
121
+ - spec/number_parser_spec.rb
104
122
  - spec/numbers_in_words_spec.rb
123
+ - spec/numerical_strings_spec.rb
105
124
  - spec/spec_helper.rb
125
+ - spec/to_word_spec.rb
106
126
  - spec/words_in_numbers_spec.rb
127
+ - spec/writer_spec.rb
128
+ - spec/years_spec.rb
@@ -1,93 +0,0 @@
1
- module NumbersInWords
2
- module English
3
- def self.exceptions
4
- {
5
- 0 => "zero",
6
- 1 => "one",
7
- 2 => "two",
8
- 3 => "three",
9
- 4 => "four",
10
- 5 => "five",
11
- 6 => "six",
12
- 7 => "seven",
13
- 8 => "eight",
14
- 9 => "nine",
15
-
16
- 10 => "ten",
17
- 11 => "eleven",
18
- 12 => "twelve",
19
-
20
- 13 => "thirteen",
21
- 14 => "fourteen",
22
- 15 => "fifteen",
23
- 16 => "sixteen" ,
24
- 17 => "seventeen",
25
- 18 => "eighteen",
26
- 19 => "nineteen",
27
-
28
- 20 => "twenty",
29
- 30 => "thirty",
30
- 40 => "forty",
31
- 50 => "fifty",
32
- 60 => "sixty",
33
- 70 => "seventy",
34
- 80 => "eighty",
35
- 90 => "ninety"
36
- }
37
- end
38
-
39
- def self.swap_keys hsh
40
- hsh.inject({}){|h,(k,v)| h[v]=k; h}
41
- end
42
-
43
- def self.powers_of_ten
44
- {
45
- 0 => "one",
46
- 1 => "ten",
47
- 2 => "hundred",
48
- 3 => "thousand",
49
- 6 => "million",
50
- 9 => "billion",
51
- 12 => "trillion",
52
- 15 => "quadrillion",
53
- 18 => "quintillion",
54
- 21 => "sextillion",
55
- 24 => "septillion",
56
- 27 => "octillion",
57
- 30 => "nonillion",
58
- 33 => "decillion",
59
- 36 => "undecillion",
60
- 39 => "duodecillion",
61
- 42 => "tredecillion",
62
- 45 => "quattuordecillion",
63
- 48 => "quindecillion",
64
- 51 => "sexdecillion",
65
- 54 => "septendecillion",
66
- 57 => "octodecillion",
67
- 60 => "novemdecillion",
68
- 63 => "vigintillion",
69
- 66 => "unvigintillion",
70
- 69 => "duovigintillion",
71
- 72 => "trevigintillion",
72
- 75 => "quattuorvigintillion",
73
- 78 => "quinvigintillion",
74
- 81 => "sexvigintillion",
75
- 84 => "septenvigintillion",
76
- 87 => "octovigintillion",
77
- 90 => "novemvigintillion",
78
- 93 => "trigintillion",
79
- 96 => "untrigintillion",
80
- 99 => "duotrigintillion",
81
- 100 => "googol"
82
- }
83
- end
84
-
85
- def self.exceptions_to_i
86
- swap_keys exceptions
87
- end
88
-
89
- def self.powers_of_ten_to_i
90
- swap_keys powers_of_ten
91
- end
92
- end
93
- end
@@ -1,109 +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
- length = number.to_s.length
27
- output = ""
28
-
29
- if length == 2 #20-99
30
- tens = (number/10).round*10 #write the tens
31
-
32
- output << exceptions[tens] # e.g. eighty
33
-
34
- digit = number - tens #write the digits
35
-
36
- output << " " + NumbersInWords.in_words(digit) unless digit==0
37
- else
38
- output << write() #longer numbers
39
- end
40
-
41
- output.strip
42
- end
43
-
44
- def handle_exception
45
- exceptions[@that] if @that.is_a?(Integer) and exceptions[@that]
46
- end
47
-
48
-
49
- def write
50
- length = @that.to_s.length
51
- output =
52
- if length == 3
53
- #e.g. 113 splits into "one hundred" and "thirteen"
54
- write_groups(2)
55
-
56
- #more than one hundred less than one googol
57
- elsif length < LENGTH_OF_GOOGOL
58
- write_groups(3)
59
-
60
- elsif length >= LENGTH_OF_GOOGOL
61
- write_googols
62
- end
63
- output.strip
64
- end
65
-
66
- def decimals
67
- int, decimals = NumberGroup.new(@that).split_decimals
68
- if int
69
- out = NumbersInWords.in_words(int) + " point "
70
- decimals.each do |decimal|
71
- out << NumbersInWords.in_words(decimal.to_i) + " "
72
- end
73
- out.strip
74
- end
75
- end
76
-
77
- private
78
-
79
- def write_googols
80
- googols, remainder = NumberGroup.new(@that).split_googols
81
- output = ""
82
-
83
- output << " " + NumbersInWords.in_words(googols) + " googol"
84
- if remainder > 0
85
- prefix = " "
86
- prefix << "and " if remainder < 100
87
- output << prefix + NumbersInWords.in_words(remainder)
88
- end
89
-
90
- output
91
- end
92
-
93
- def write_groups group
94
- #e.g. 113 splits into "one hundred" and "thirteen"
95
- output = ""
96
- group_words(group) do |power, name, digits|
97
- if digits > 0
98
- prefix = " "
99
- #no and between thousands and hundreds
100
- prefix << "and " if power == 0 and digits < 100
101
- output << prefix + NumbersInWords.in_words(digits)
102
- output << prefix + name unless power == 0
103
- end
104
- end
105
- output
106
- end
107
- end
108
- end
109
- end
@@ -1,31 +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
-
19
- def group_words size
20
- #1000 and over Numbers are split into groups of three
21
- groups = NumberGroup.groups_of @that, size
22
- powers = groups.keys.sort.reverse #put in descending order
23
-
24
- powers.each do |power|
25
- name = powers_of_ten[power]
26
- digits = groups[power]
27
- yield power, name, digits
28
- end
29
- end
30
- end
31
- end
@@ -1,81 +0,0 @@
1
- module NumbersInWords::NumberParser
2
- # Example: 364,895,457,898
3
- #three hundred and sixty four billion eight hundred and ninety five million
4
- #four hundred and fifty seven thousand eight hundred and ninety eight
5
- #
6
- #3 100 60 4 10^9, 8 100 90 5 10^6, 4 100 50 7 1000, 8 100 90 8
7
- # memory answer
8
- #x1. 3 add to memory because answer and memory are zero 3 0
9
- #x2. memory * 100 (because memory<100) 300 0
10
- #x3. 60 add to memory because memory > 60 360 0
11
- #x3. 4 add to memory because memory > 4 364 0
12
- #x4. multiply memory by 10^9 because memory < power of ten 364*10^9 0
13
- #x5. add memory to answer (and reset)memory > 8 (memory pow of ten > 2) 0 364*10^9
14
- #x6. 8 add to memory because not finished 8 ''
15
- #x7. multiply memory by 100 because memory < 100 800 ''
16
- #x8. add 90 to memory because memory > 90 890 ''
17
- #x9. add 5 to memory because memory > 5 895 ''
18
- #x10. multiply memory by 10^6 because memory < power of ten 895*10^6 ''
19
- #x11. add memory to answer (and reset) because memory power ten > 2 0 364895 * 10^6
20
- #x12. 4 add to memory because not finished 4 ''
21
- #x13. memory * 100 because memory < 100 400 ''
22
- #x14. memory + 50 because memory > 50 450 ''
23
- #x15. memory + 7 because memory > 7 457 ''
24
- #x16. memory * 1000 because memory < 1000 457000 ''
25
- #x17. add memory to answer (and reset)memory > 8 (memory pow of ten > 2) 0 364895457000
26
- #x18. 8 add to memory because not finished 8 ''
27
- #x19. memory * 100 because memory < 100 800 ''
28
- #x14. memory + 90 because memory > 90 890 ''
29
- #x15. memory + 8 because memory > 8 898 ''
30
- #16. finished so add memory to answer
31
-
32
- #Example
33
- #2001
34
- #two thousand and one
35
- #2 1000 1
36
- # memory answer
37
- #1. add 2 to memory because first 2 0
38
- #2. multiply memory by 1000 because memory < 1000 2000 0
39
- #3. add memory to answer,reset, because power of ten>2 0 2000
40
- #4. add 1 to memory 1 2000
41
- #5. finish - add memory to answer 0 2001
42
- def parse(integers)
43
- memory = 0
44
- answer = 0
45
- reset = true #reset each time memory is reset
46
- integers.each do |integer|
47
- if reset
48
- reset = false
49
- memory += integer
50
- else
51
- #x4. multiply memory by 10^9 because memory < power of ten
52
- if power_of_ten?(integer)
53
- if power_of_ten(integer)> 2
54
- memory *= integer
55
- #17. add memory to answer (and reset) (memory pow of ten > 2)
56
- answer += memory
57
- memory = 0
58
- reset = true
59
- end
60
- end
61
-
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 power_of_ten integer
73
- Math.log10(integer)
74
- end
75
-
76
- def power_of_ten? integer
77
- power_of_ten(integer) == power_of_ten(integer).to_i
78
- end
79
-
80
- extend self
81
- end