numbers_in_words 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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