dictable 0.1.4 → 0.1.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '012759946bfcad31c242d510beaefdee1cf8508cbd9ec33aa6de60d681c0d823'
4
- data.tar.gz: f33ef1f5cc079d1e21cbb06ae546ffaac3736066af62ef36b9d3af6809a44067
3
+ metadata.gz: 5bce84832eecc44c3b43987ab5a20d95fad7b135f5b14febd2e0cccccb414654
4
+ data.tar.gz: f02c799cf5ee3928c6d26adac75f9c84bbc02a335cb8d89579e90cbd605152fb
5
5
  SHA512:
6
- metadata.gz: 1c98192e82814e00163eb10f85703300c55d4c75623c31599544da70cebadf4985c3c04a5c36cad9aaef1ca2c31f06a83361ff38bb34aea5b6502ce86fba5ea5
7
- data.tar.gz: b4b48b2ac632a3115aa38bb62038a2354de1540f1ec6b27ba6f3675b8dffb71c9f4aab7751454b95742bc162dd035a4ff3590fcd58ad7cf77bddbd4210b6b635
6
+ metadata.gz: 1c8d79925d5b9495fb525c0d5d0c141aca3667c73ef37ae0f203a434f93e151fa30577e963463edf6b2b44572af712182c3acd0d78d44943b996764713acd275
7
+ data.tar.gz: f98accf83447ec44cd1162a5bd5b07b2ecd0b1bca26d4d1f957a47cab0285805b47ab097cce742f565a79595b3890163eaf2bc6155b0d456c7d129e4ef8e3a7d
data/CHANGELOG.md CHANGED
@@ -24,4 +24,14 @@
24
24
  ## [0.1.4] - 2024-01-14
25
25
 
26
26
  - Refactor to use instance methods to avoid exposing so many
27
- - Added rubocop and fixed all errors
27
+ - Added rubocop and fixed all errors
28
+
29
+ ## [0.1.5] - 2024-03-01
30
+
31
+ - Refactor to simplify
32
+ - Supporting leading zeroes is out of scope
33
+ - Added dictionaries to explode address abbreviations
34
+
35
+ ## [0.1.6] - 2024-03-01
36
+
37
+ - Fix issue with dictionaries not loading when importing the gem in another project
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Dictable
2
2
 
3
- GitHub Copilot: Dictable is an opinionated Ruby gem designed to convert numbers into their spoken equivalents. This gem is particularly useful in situations where precise verbal communication of numbers is required, such as during phone calls or dictation. It makes certain decisions about the "best" way to pronounce numbers, which may be subject to debate.
3
+ Ever encountered the challenge of ensuring your text-to-speech applications pronounce addresses just the way most people in the U.S. do? Dictable is here to bridge that gap. This Ruby Gem transforms addresses like `1234 N Lasalle Ave` into their spoken-word equivalents, such as `twelve thirty four north lasalle avenue`, optimizing them for clear and natural dictation.
4
+
5
+ Our approach to converting numbers into words is opinionated and intentionally avoids frequent use of "hundred" and "thousand" unless common usage dictates otherwise. The goal? To closely replicate the nuanced way addresses are articulated in everyday conversation across the U.S. Dive into the examples from our tests to see the difference in action.
6
+
7
+ In a landscape where text-to-voice platforms each have their unique way of pronouncing numbers, as of March 2024, Dictable hands you the reins for more consistent and predictable address dictation.
4
8
 
5
9
  ## Installation
6
10
 
@@ -29,27 +33,49 @@ To use Dictable, simply call the `to_dictable` method on any `Integer`, this con
29
33
  ```ruby
30
34
  require 'dictable'
31
35
 
32
- puts 123.to_dictable
33
- # Output: "one twenty three"
36
+ puts Dictable.address('2300 N Lincoln Park St')
37
+ # > 'twenthy three hundred North Lincoln Park Street'
34
38
 
35
- puts "1243".to_dictable_number
36
- # Output: "twelve forty three"
37
39
  ```
38
40
 
39
41
  ## Example
40
- List of samples from specs:
41
-
42
- - `100` is converted to `one hundred`
43
- - `123` is converted to `one twenty three`
44
- - `'001'` is converted to `zero zero one`
45
- - `'010'` is converted to `zero ten`
46
- - `'0000'` is converted to `zero zero zero zero`
47
- - `1000` is converted to `one thousand`
48
- - `4321` is converted to `forty three twenty one`
49
- - `4300` is converted to `forty three hundred`
50
- - `'0001'` is converted to `zero zero zero one`
51
- - `'0010'` is converted to `zero zero ten`
52
- - `'0100'` is converted to `zero one hundred`
42
+ List of samples from specs for addresses:
43
+
44
+ ```
45
+ Dictable::StreetName
46
+ converts 1234 N Lasalle Ave to 1234 north lasalle avenue
47
+ converts 1234 E Chelsea Rd to 1234 east chelsea road
48
+ converts 1234 s Chelsea st to 1234 south chelsea street
49
+ converts 1234 w Chelsea Blvd to 1234 west chelsea boulevard
50
+ converts 1234 N Clifford Dr to 1234 north clifford drive
51
+ converts 1234 E Chelsea Ct to 1234 east chelsea court
52
+ converts 1234 S Chelsea pl to 1234 south chelsea place
53
+ converts 1234 S Chelsea Pl Gandalf to 1234 south chelsea place gandalf
54
+ converts 1234 W Chelsea Ter to 1234 west chelsea terrace
55
+
56
+ Dictable::StreetNumber
57
+ converts 0 to zero
58
+ converts 5 to five
59
+ converts 10 to ten
60
+ converts 21 to twenty one
61
+ converts 100 to one hundred
62
+ converts 103 to one hundred three
63
+ converts 303 to three hundred three
64
+ converts 123 to one twenty three
65
+ converts 323 to three twenty three
66
+ converts 1000 to one thousand
67
+ converts 4321 to forty three twenty one
68
+ converts 4300 to forty three hundred
69
+ converts 1900 to nineteen hundred
70
+ converts 32323 to thirty two three twenty three
71
+
72
+ Dictable
73
+ #address
74
+ converts 1234 N Lasalle Ave to twelve thirty four north lasalle avenue
75
+ converts 123 S Lasalle rd to one twenty three south lasalle road
76
+ converts 1500 s Lasalle Rd to fifteen hundred south lasalle road
77
+
78
+ ```
53
79
 
54
80
  Please note that the numbers in quotes are treated as strings, which allows leading zeroes to be preserved.
55
81
 
@@ -63,4 +89,4 @@ Bug reports and pull requests are welcome on GitHub. This project aims to be a s
63
89
 
64
90
  ## License
65
91
 
66
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
92
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/dictable.gemspec CHANGED
@@ -8,9 +8,11 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Matias Verges']
9
9
  spec.email = ['matis@matis.io']
10
10
 
11
- spec.summary = 'Transform numbers into words to dictate them easily.'
12
- spec.description = 'Transform numbers into words to dictate them easily.' \
13
- "For example 1234 becomes twelve thirty four and 123456 becomes 'one two three, four five six'"
11
+ spec.summary = 'Transform street numbers into words to dictate them easily, and explodes street names abbreviations.'
12
+ spec.description =
13
+ 'Transform street numbers into words to dictate them easily, and explodes street names abbreviations.' \
14
+ "For example 1234 becomes twelve thirty four and 123456 becomes 'one two three, four five six'"
15
+
14
16
  spec.homepage = 'https://github.com/matismasters/dictable'
15
17
  spec.required_ruby_version = '>= 2.6.0'
16
18
 
@@ -0,0 +1,206 @@
1
+ ---
2
+ n: north
3
+ s: south
4
+ e: east
5
+ w: west
6
+ aly: alley
7
+ anx: anex
8
+ arc: arcade
9
+ ave: avenue
10
+ byu: bayou
11
+ bch: beach
12
+ bnd: bend
13
+ blf: bluff
14
+ blfs: bluffs
15
+ btm: bottom
16
+ blvd: boulevard
17
+ br: branch
18
+ brg: bridge
19
+ brk: brook
20
+ brks: brooks
21
+ bg: burg
22
+ bgs: burgs
23
+ byp: bypass
24
+ cp: camp
25
+ cyn: canyon
26
+ cpe: cape
27
+ cswy: causeway
28
+ ctr: center
29
+ ctrs: centers
30
+ cir: circle
31
+ cirs: circles
32
+ clf: cliff
33
+ clfs: cliffs
34
+ clb: club
35
+ cmn: common
36
+ cmns: commons
37
+ cor: corner
38
+ cors: corners
39
+ crse: course
40
+ ct: court
41
+ cts: courts
42
+ cv: cove
43
+ cvs: coves
44
+ crk: creek
45
+ cres: crescent
46
+ crst: crest
47
+ xing: crossing
48
+ xrd: crossroad
49
+ xrds: crossroads
50
+ curv: curve
51
+ dl: dale
52
+ dm: dam
53
+ dv: divide
54
+ dr: drive
55
+ drs: drives
56
+ est: estate
57
+ ests: estates
58
+ expy: expressway
59
+ ext: extension
60
+ exts: extensions
61
+ fls: falls
62
+ fry: ferry
63
+ fld: field
64
+ flds: fields
65
+ flt: flat
66
+ flts: flats
67
+ frd: ford
68
+ frds: fords
69
+ frst: forest
70
+ frg: forge
71
+ frgs: forges
72
+ frk: fork
73
+ frks: forks
74
+ ft: fort
75
+ fwy: freeway
76
+ gdn: garden
77
+ gdns: gardens
78
+ gtwy: gateway
79
+ gln: glen
80
+ glns: glens
81
+ grn: green
82
+ grns: greens
83
+ grv: grove
84
+ grvs: groves
85
+ hbr: harbor
86
+ hbrs: harbors
87
+ hvn: haven
88
+ hts: heights
89
+ hwy: highway
90
+ hl: hill
91
+ hls: hills
92
+ holw: hollow
93
+ inlt: inlet
94
+ is: island
95
+ iss: islands
96
+ isle: isles
97
+ jct: junction
98
+ jcts: junctions
99
+ ky: key
100
+ kys: keys
101
+ knl: knoll
102
+ knls: knolls
103
+ lk: lake
104
+ lks: lakes
105
+ land: land
106
+ lndg: landing
107
+ ln: lane
108
+ lgt: light
109
+ lgts: lights
110
+ lf: loaf
111
+ lck: lock
112
+ lcks: locks
113
+ ldg: lodge
114
+ loop: loops
115
+ mall: mall
116
+ mnr: manor
117
+ mnrs: manors
118
+ mdw: meadow
119
+ mdws: meadows
120
+ mews: mews
121
+ ml: mill
122
+ mls: mills
123
+ msn: mission
124
+ mtwy: motorway
125
+ mt: mount
126
+ mtn: mountain
127
+ mtns: mountains
128
+ nck: neck
129
+ orch: orchard
130
+ oval: ovl
131
+ opas: overpass
132
+ park: parks
133
+ pkwy: parkway
134
+ pass: pass
135
+ psge: passage
136
+ path: paths
137
+ pike: pikes
138
+ pne: pine
139
+ pnes: pines
140
+ pl: place
141
+ pln: plain
142
+ plns: plains
143
+ plz: plaza
144
+ pt: point
145
+ pts: points
146
+ prt: port
147
+ prts: ports
148
+ pr: prairie
149
+ radl: radial
150
+ ramp: ramp
151
+ rnch: ranch
152
+ rpd: rapid
153
+ rpds: rapids
154
+ rst: rest
155
+ rdg: ridge
156
+ rdgs: ridges
157
+ riv: river
158
+ rd: road
159
+ rds: roads
160
+ rte: route
161
+ row: row
162
+ rue: rue
163
+ run: run
164
+ shl: shoal
165
+ shls: shoals
166
+ shr: shore
167
+ shrs: shores
168
+ skwy: skyway
169
+ spg: spring
170
+ spgs: springs
171
+ spur: spurs
172
+ sq: square
173
+ sqs: squares
174
+ sta: station
175
+ stra: stravenue
176
+ strm: stream
177
+ st: street
178
+ sts: streets
179
+ smt: summit
180
+ ter: terrace
181
+ trwy: throughway
182
+ trce: trace
183
+ trak: track
184
+ trfy: trafficway
185
+ trl: trail
186
+ trlr: trailer
187
+ tunl: tunnel
188
+ tpke: turnpike
189
+ upas: underpass
190
+ un: union
191
+ uns: unions
192
+ vly: valley
193
+ vlys: valleys
194
+ via: viaduct
195
+ vw: view
196
+ vws: views
197
+ vlg: village
198
+ vlgs: villages
199
+ vl: ville
200
+ vis: vista
201
+ walk: walks
202
+ wall: wall
203
+ way: wy
204
+ ways: ways
205
+ wl: well
206
+ wls: wells
@@ -0,0 +1,32 @@
1
+ ---
2
+ "0": zero
3
+ "00": hundred # this enables the hundreds but also 15 hundred 36 hundred etc
4
+ "000": thousand
5
+ "1": one
6
+ "2": two
7
+ "3": three
8
+ "4": four
9
+ "5": five
10
+ "6": six
11
+ "7": seven
12
+ "8": eight
13
+ "9": nine
14
+ "10": ten
15
+ "11": eleven
16
+ "12": twelve
17
+ "13": thirteen
18
+ "14": fourteen
19
+ "15": fifteen
20
+ "16": sixteen
21
+ "17": seventeen
22
+ "18": eighteen
23
+ "19": nineteen
24
+ "20": twenty
25
+ "30": thirty
26
+ "40": forty
27
+ "50": fifty
28
+ "60": sixty
29
+ "70": seventy
30
+ "80": eighty
31
+ "90": ninety
32
+
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dictable
4
+ class StreetName
5
+ def initialize(street_number, lang: :en)
6
+ @street_number = street_number.downcase
7
+ @dictionary = Dictable.load_dictionary(:address_abbreviations_exploded, lang: lang)
8
+ end
9
+
10
+ def to_dictable
11
+ @street_number.split.map { |word| @dictionary[word.downcase] || word }.join(' ')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dictable
4
+ class StreetNumber
5
+ def initialize(street_number, lang: :en)
6
+ @street_number = street_number
7
+ @dictionary = Dictable.load_dictionary(:numbers_to_words, lang: lang)
8
+ end
9
+
10
+ def to_dictable
11
+ # less than 20 or multiples of 10
12
+ @dictionary.key?(@street_number)
13
+ return @dictionary[@street_number] if @dictionary.key?(@street_number)
14
+
15
+ # 100, 200, ... 900 and 1000, 2000, ... 9000
16
+ return plain_hundreds_or_thousands_to_words(@street_number) if hundreds_or_thousands?(@street_number)
17
+
18
+ # 20 or more and less than 100
19
+ return two_digit_number_to_words(@street_number) if @street_number.length == 2
20
+
21
+ # 5 digit addresses are rare, and we'll be opinionated and pronounce them as two digits, one digit, and two digits
22
+ return five_digit_number_to_words(@street_number) if @street_number.length == 5
23
+
24
+ # now everythinge else
25
+ parse_in_pairs(@street_number)
26
+ end
27
+
28
+ private
29
+
30
+ def hundreds_or_thousands?(number)
31
+ number[1..].to_i.zero? && (number.length == 3 || number.length == 4)
32
+ end
33
+
34
+ def plain_hundreds_or_thousands_to_words(number)
35
+ "#{@dictionary[number[0]]} #{@dictionary[number[1..]]}"
36
+ end
37
+
38
+ def five_digit_number_to_words(number)
39
+ [two_digit_number_to_words(number[0..1]), @dictionary[number[2]],
40
+ two_digit_number_to_words(number[3..])].join(' ')
41
+ end
42
+
43
+ def two_digit_number_to_words(number)
44
+ @dictionary[number] || "#{@dictionary["#{number[0]}0"]} #{@dictionary[number[1]]}"
45
+ end
46
+
47
+ def parse_in_pairs(number)
48
+ parts = []
49
+
50
+ # for 3 digit numbers, we extract the first digit and pronounce it as a single digit number
51
+ if number.length == 3
52
+ parts << @dictionary[number[0]]
53
+ number = number[1..]
54
+ end
55
+
56
+ parts += number.scan(/../).map { |pair| two_digit_number_to_words(pair) }
57
+ parts.join(' ')
58
+ end
59
+ end
60
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dictable
4
- VERSION = '0.1.4'
4
+ VERSION = '0.1.6'
5
5
  end
data/lib/dictable.rb CHANGED
@@ -2,45 +2,33 @@
2
2
 
3
3
  # lib/dictable.rb
4
4
  require_relative 'dictable/version'
5
- require_relative 'dictable/extend_primitives'
6
- require_relative 'dictable/exceptions'
7
- require_relative 'dictable/dictable_number'
5
+ require_relative 'dictable/street_name'
6
+ require_relative 'dictable/street_number'
7
+ require 'yaml'
8
8
 
9
9
  # We are going to change the design of the gem to make it more flexible.
10
-
11
- module DictableNumber
12
- class Base
13
- def initialize(number:)
14
- @number = number
15
- end
16
-
17
- def to_dictable
18
- raise NotImplementedError
19
- end
10
+ module Dictable
11
+ def self.address(address, lang: :en)
12
+ address_parts = address.split
13
+ street_number = address_parts.shift
14
+ street_address = address_parts.join(' ')
15
+
16
+ [
17
+ number_to_words(street_number, lang: lang),
18
+ explode_abberviations(street_address, lang: lang)
19
+ ].join(' ')
20
20
  end
21
21
 
22
- module Transformers
23
-
24
-
25
- end
26
-
27
- =begin
28
-
29
- module DictableNumber; end
30
- class DictableNumber::Base; end
31
-
32
- # Each language will have a dictionary
33
- module DictableNumber::English; end
34
- module DictableNumber::Spanish; end
35
-
36
- # this is the explanation of the adapter pattern
37
- # https://refactoring.guru/design-patterns/adapter/ruby/example
38
-
39
-
40
-
41
-
42
-
22
+ def self.number_to_words(street_number, lang:)
23
+ StreetNumber.new(street_number, lang: lang).to_dictable
24
+ end
43
25
 
26
+ def self.explode_abberviations(address, lang:)
27
+ StreetName.new(address, lang: lang).to_dictable
28
+ end
44
29
 
30
+ def self.load_dictionary(name, lang: :en)
31
+ dictionary_path = File.join(__dir__, '../dictionaries', lang.to_s, "#{name}.yml")
32
+ YAML.load_file(dictionary_path)
33
+ end
45
34
  end
46
-
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dictable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matias Verges
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-04 00:00:00.000000000 Z
11
+ date: 2024-03-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Transform numbers into words to dictate them easily.For example 1234
14
- becomes twelve thirty four and 123456 becomes 'one two three, four five six'
13
+ description: Transform street numbers into words to dictate them easily, and explodes
14
+ street names abbreviations.For example 1234 becomes twelve thirty four and 123456
15
+ becomes 'one two three, four five six'
15
16
  email:
16
17
  - matis@matis.io
17
18
  executables: []
@@ -25,10 +26,11 @@ files:
25
26
  - README.md
26
27
  - Rakefile
27
28
  - dictable.gemspec
29
+ - dictionaries/en/address_abbreviations_exploded.yml
30
+ - dictionaries/en/numbers_to_words.yml
28
31
  - lib/dictable.rb
29
- - lib/dictable/dictable_number.rb
30
- - lib/dictable/exceptions.rb
31
- - lib/dictable/extend_primitives.rb
32
+ - lib/dictable/street_name.rb
33
+ - lib/dictable/street_number.rb
32
34
  - lib/dictable/version.rb
33
35
  - sig/dictable.rbs
34
36
  homepage: https://github.com/matismasters/dictable
@@ -57,5 +59,6 @@ requirements: []
57
59
  rubygems_version: 3.4.22
58
60
  signing_key:
59
61
  specification_version: 4
60
- summary: Transform numbers into words to dictate them easily.
62
+ summary: Transform street numbers into words to dictate them easily, and explodes
63
+ street names abbreviations.
61
64
  test_files: []
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dictable
4
- class DictableNumber
5
- attr_reader :number_to_dictate, :dictable_number_in_words
6
-
7
- ONES = %w[zero one two three four five six seven eight nine].freeze
8
- TEENS = %w[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen].freeze
9
- TENS = %w[twenty thirty forty fifty sixty seventy eighty ninety].freeze
10
-
11
- def initialize(number_to_dictate)
12
- @number_to_dictate = number_to_dictate.to_s
13
- validate_number(@number_to_dictate)
14
- end
15
-
16
- def to_dictable
17
- @to_dictable ||= number_to_words
18
- end
19
-
20
- private
21
-
22
- def number_to_words
23
- number_as_string = @number_to_dictate
24
-
25
- leading_zeroes_words = leading_zeroes_to_words(number_as_string)
26
-
27
- number_without_leading_zeroes = number_without_leading_zeroes(number_as_string)
28
- number_without_leading_zeroes_words = number_without_leading_zeroes_to_words(number_without_leading_zeroes)
29
-
30
- [leading_zeroes_words, number_without_leading_zeroes_words].reject(&:empty?).join(' ')
31
- end
32
-
33
- def validate_number(number_as_string)
34
- raise NonNumberCharactersPresent if number_as_string.match?(/[^0-9]/)
35
- end
36
-
37
- def number_without_leading_zeroes_to_words(number_as_string)
38
- case number_as_string.length
39
- when 1 then one_digit_number_to_words(number_as_string)
40
- when 2 then two_digit_number_to_words(number_as_string)
41
- when 3 then three_digit_number_to_words(number_as_string)
42
- when 4 then four_digit_number_to_words(number_as_string)
43
- else large_number_to_words(number_as_string)
44
- end
45
- end
46
-
47
- def repeat_zeroes(number_of_zeroes)
48
- Array.new(number_of_zeroes) { ONES[0] }.join(' ')
49
- end
50
-
51
- def leading_zeroes_to_words(number_as_string)
52
- leading_zeroes = number_as_string.match(/^0+/).to_s
53
- return '' if leading_zeroes.empty?
54
-
55
- repeat_zeroes(leading_zeroes.length)
56
- end
57
-
58
- def number_without_leading_zeroes(number_as_string)
59
- number_as_string.sub(/^0+/, '')
60
- end
61
-
62
- def single_thousands_to_words(number_as_string)
63
- number = number_as_string.to_i / 1000
64
-
65
- [one_digit_number_to_words(number), 'thousand'].join(' ')
66
- end
67
-
68
- def one_digit_number_to_words(number_as_string)
69
- number = number_as_string.to_i
70
- return repeat_zeroes(1) if number.zero?
71
-
72
- ONES[number]
73
- end
74
-
75
- def two_digit_number_to_words(number_as_string)
76
- number = number_as_string.to_i
77
-
78
- return repeat_zeroes(2) if number.zero?
79
- return TEENS[number - 10] if number < 20
80
-
81
- div, mod = number.divmod(10)
82
- TENS[div - 2] + (mod.zero? ? '' : " #{ONES[mod]}")
83
- end
84
-
85
- def three_digit_number_to_words(number_as_string)
86
- number = number_as_string.to_i
87
- return repeat_zeroes(3) if number.zero?
88
-
89
- first_digit, remainder = number.divmod(100)
90
- words = [ONES[first_digit]]
91
- words << (remainder.zero? ? 'hundred' : two_digit_number_to_words(remainder))
92
- words.join(' ')
93
- end
94
-
95
- def four_digit_number_to_words(number_as_string)
96
- number = number_as_string.to_i
97
-
98
- return repeat_zeroes(4) if number.zero?
99
- return single_thousands_to_words(number_as_string) if (number % 1000).zero?
100
-
101
- high_pair = number_as_string[0..1]
102
- low_pair = number_as_string[2..3]
103
-
104
- [
105
- two_digit_number_to_words(high_pair),
106
- low_pair.to_i.zero? ? 'hundred' : two_digit_number_to_words(low_pair)
107
- ].join(' ')
108
- end
109
-
110
- def large_number_to_words(number_as_string)
111
- number_as_string.chars.map { |digit| ONES[digit.to_i] }.each_slice(3).map { |digit| digit.join(' ') }.join(', ')
112
- end
113
- end
114
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dictable
4
- class Error < StandardError; end
5
-
6
- class NonNumberCharactersPresent < StandardError
7
- def initialize
8
- super('Non-number characters present')
9
- end
10
- end
11
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Integer
4
- def to_dictable
5
- Dictable::DictableNumber.new(self).to_dictable
6
- end
7
- end
8
-
9
- class String
10
- def to_dictable_number
11
- Dictable::DictableNumber.new(self).to_dictable
12
- end
13
- end