cousin_roman 0.0.2 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d721d30a8c9bfff8692b8be996a4b10697fb2d60
4
- data.tar.gz: 9134a9f70a990f750a4c904daaa90878aefd6552
3
+ metadata.gz: f16dc19c0864ea51d64a45d94b4a0acf07cea72b
4
+ data.tar.gz: d0bd841b1ab1c55cb9ed88ef4671a9d9a134820c
5
5
  SHA512:
6
- metadata.gz: 6fd61fa7907ce017e491be441e96f00c51e94cb67ac1407965dc15bb3d41caf118f4b4898fe3a885cd0d117b911182aa4a5ce363bb674f0c13d1ca25ae76c919
7
- data.tar.gz: fa39c4136a8b29e9d7d7408a37716ed423f1144cf6422b98368838a640ae1b82ee9b2056db4b7de2cc86f7166cb919184cf609d4122708b27db556092a488321
6
+ metadata.gz: ec7600e60f73656ed7aefa6c1bdaf6a36e70d29943becb1f2d9115cf20f43eb7cc052228d85ad08d74c85e2d996ef5a82bfb395efe46bbadcfaecd7720643ea6
7
+ data.tar.gz: 9e41c6a9c0f41a90d47258623b6e8088dff534add7ff06ef8d69f2303cbf01c8c00de59bf5f31f4162d513a434eee36838ce7ebeafc6d56817746333c5727283
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # CousinRoman
2
2
 
3
- `CousinRoman` is a `String` extension which allows you to convert
4
- Roman numerals (following modern subtractive notation)
5
- to Arabic numbers (i.e. Integers).
3
+ `CousinRoman` provides functionality to convert between Roman and Arabian numerals.
4
+
5
+ The functionality provided via String and Integer extensions.
6
6
 
7
7
  ## Installation
8
8
 
@@ -20,14 +20,22 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- Just use `String#to_arabic` or `String#to_arabic!` method.
23
+ Just use `String#to_arabian` or `String#to_arabian!` methods
24
+ if you want to convert from Roman to Arabian
25
+ and
26
+ `Integer#to_roman` or `Integer#to_roman!`
27
+ if you want to convert from Arabian to Roman.
24
28
 
25
29
  For example:
26
30
 
27
31
  ```ruby
28
- 'MMXIII'.to_arabic # => 2013
29
- 'MMYUOX'.to_arabic # => nil
30
- 'MMYOUX'.to_arabic! # => TypeError: not a valid roman number
32
+ 'MMXIII'.to_arabian # => 2013
33
+ 'MMYUOX'.to_arabian # => nil
34
+ 'MMYOUX'.to_arabian! # => TypeError: not a valid roman number
35
+
36
+ 2013.to_roman # => 'MMXIII'
37
+ '0'.to_roman # => nil
38
+ '100500'.to_roman # => TypeError: not a valid roman number
31
39
  ```
32
40
 
33
41
  ## Testing
@@ -36,7 +44,7 @@ Just run
36
44
 
37
45
  $ rake
38
46
 
39
- under gem folder.
47
+ under gem folder (be prepared for massive output).
40
48
 
41
49
  ## Contributing
42
50
 
data/cousin_roman.gemspec CHANGED
@@ -8,14 +8,14 @@ Gem::Specification.new do |spec|
8
8
  spec.version = CousinRoman::VERSION
9
9
  spec.authors = ["Artem Pyanykh"]
10
10
  spec.email = ["artem.pyanykh@gmail.com"]
11
- spec.description = %q{Easily convert Roman numerals to Integers. Functionality provided via String extension}
12
- spec.summary = %q{Convert Roman numerals to Integers}
11
+ spec.description = %q{Easily convert Roman and Arabian number. Functionality provided via String and extensions}
12
+ spec.summary = %q{Convert Roman numerals to Integers and vice versa}
13
13
  spec.homepage = "https://github.com/ArtemPyanykh/cousin_roman"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)*/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
@@ -0,0 +1,69 @@
1
+ require 'cousin_roman'
2
+
3
+ module CousinRoman
4
+ module Arabian
5
+ extend self
6
+
7
+ def valid?(number)
8
+ number.is_a? Integer and number >= 1 and number <= 3999
9
+ end
10
+
11
+ def to_roman(arabian)
12
+ convert arabian if valid? arabian
13
+ end
14
+
15
+ def to_roman!(arabian)
16
+ if valid? arabian
17
+ convert arabian
18
+ else
19
+ raise TypeError, 'not a valid roman number'
20
+ end
21
+ end
22
+
23
+ def convert(number)
24
+ thousands = number / 1000
25
+ hundreds = number / 100 % 10
26
+ tens = number / 10 % 10
27
+ ones = number % 10
28
+
29
+ build_roman(thousands, hundreds, tens, ones).upcase
30
+ end
31
+
32
+ def build_roman(thousands, hundreds, tens, ones)
33
+ build_pow(thousands, 4) +
34
+ build_pow(hundreds, 3) +
35
+ build_pow(tens, 2) +
36
+ build_pow(ones, 1)
37
+ end
38
+
39
+ def build_pow(number, pow)
40
+ literals = pow_literals(pow)
41
+
42
+ case number
43
+ when 1..3 then literals[:one]*number
44
+ when 4 then literals[:subtractives][4]
45
+ when 5..8 then literals[:five] + (literals[:one]*(number - 5))
46
+ when 9 then literals[:subtractives][9]
47
+ else ""
48
+ end
49
+ end
50
+
51
+ def pow_literals(pow)
52
+ one_literal, _ = ONES.find do |literal, value|
53
+ value >= 10 ** (pow - 1) and value < 10 ** pow
54
+ end
55
+ five_literal, _ = FIVES.find do |literal, value|
56
+ value >= 10 ** (pow - 1) and value < 10 ** pow
57
+ end
58
+ subtractive_literals = {}
59
+ SUBTRACTIVES.select do |literal, value|
60
+ value >= 10 ** (pow - 1) and value < 10 ** pow
61
+ end.each do |literal, number|
62
+ order = number / (10 ** (pow - 1))
63
+ subtractive_literals[order] = literal
64
+ end
65
+
66
+ {one: one_literal, five: five_literal, subtractives: subtractive_literals}
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ require "cousin_roman/roman"
2
+
3
+ class Integer
4
+ def to_roman
5
+ CousinRoman::Arabian.to_roman(self)
6
+ end
7
+
8
+ def to_roman!
9
+ CousinRoman::Arabian.to_roman!(self)
10
+ end
11
+ end
@@ -1,39 +1,9 @@
1
- module CousinRoman
2
- LITERALS = [
3
- 'i', 'I',
4
- 'v', 'V',
5
- 'x', 'X',
6
- 'l', 'L',
7
- 'c', 'C',
8
- 'd', 'D',
9
- 'm', 'M'
10
- ]
11
-
12
- ONES = {
13
- 'i' => 1,
14
- 'x' => 10,
15
- 'c' => 100,
16
- 'm' => 1000
17
- }
18
-
19
- FIVES = {
20
- 'v' => 5,
21
- 'l' => 50,
22
- 'd' => 500,
23
- }
1
+ require 'cousin_roman'
24
2
 
25
- SUBTRACTIVE = {
26
- 'iv' => 4,
27
- 'ix' => 9,
28
- 'xl' => 40,
29
- 'xc' => 90,
30
- 'cd' => 400,
31
- 'cm' => 900,
32
- }
33
-
34
- FACTORS = ONES.merge(FIVES).merge(SUBTRACTIVE)
3
+ module CousinRoman
4
+ module Roman
5
+ extend self
35
6
 
36
- class << self
37
7
  def valid?(number)
38
8
  matches = number.match roman_regex
39
9
  matches and !matches[0].empty?
@@ -50,7 +20,7 @@ module CousinRoman
50
20
  # 2. Sum this numeric values to get the final answer
51
21
  def convert(number)
52
22
  intermediate = number.dup.downcase
53
- SUBTRACTIVE.each do |factor, value|
23
+ SUBTRACTIVES.each do |factor, value|
54
24
  intermediate.gsub!(factor, "(#{value})")
55
25
  end
56
26
  ONES.merge(FIVES).each do |factor, value|
@@ -62,12 +32,12 @@ module CousinRoman
62
32
  end
63
33
  end
64
34
 
65
- def to_arabic(number)
35
+ def to_arabian(number)
66
36
  clean = number.strip
67
37
  convert clean if valid? clean
68
38
  end
69
39
 
70
- def to_arabic!(number)
40
+ def to_arabian!(number)
71
41
  clean = number.strip
72
42
  if valid? clean
73
43
  convert clean
@@ -1,11 +1,11 @@
1
- require "cousin_roman/conversion"
1
+ require "cousin_roman/roman"
2
2
 
3
3
  class String
4
- def to_arabic
5
- CousinRoman.to_arabic(self)
4
+ def to_arabian
5
+ CousinRoman::Roman.to_arabian(self)
6
6
  end
7
7
 
8
- def to_arabic!
9
- CousinRoman.to_arabic!(self)
8
+ def to_arabian!
9
+ CousinRoman::Roman.to_arabian!(self)
10
10
  end
11
11
  end
@@ -1,3 +1,3 @@
1
1
  module CousinRoman
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/cousin_roman.rb CHANGED
@@ -1,3 +1,41 @@
1
1
  require "cousin_roman/version"
2
- require "cousin_roman/conversion"
2
+ require "cousin_roman/roman"
3
+ require "cousin_roman/arabian"
3
4
  require "cousin_roman/string_extension"
5
+ require "cousin_roman/integer_extension"
6
+
7
+ module CousinRoman
8
+ LITERALS = [
9
+ 'i', 'I',
10
+ 'v', 'V',
11
+ 'x', 'X',
12
+ 'l', 'L',
13
+ 'c', 'C',
14
+ 'd', 'D',
15
+ 'm', 'M'
16
+ ]
17
+
18
+ ONES = {
19
+ 'i' => 1,
20
+ 'x' => 10,
21
+ 'c' => 100,
22
+ 'm' => 1000
23
+ }
24
+
25
+ FIVES = {
26
+ 'v' => 5,
27
+ 'l' => 50,
28
+ 'd' => 500,
29
+ }
30
+
31
+ SUBTRACTIVES = {
32
+ 'iv' => 4,
33
+ 'ix' => 9,
34
+ 'xl' => 40,
35
+ 'xc' => 90,
36
+ 'cd' => 400,
37
+ 'cm' => 900,
38
+ }
39
+
40
+ FACTORS = ONES.merge(FIVES).merge(SUBTRACTIVES)
41
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe CousinRoman::Arabian do
4
+ describe 'valid?' do
5
+ it 'should consider invalid numbers <= 0' do
6
+ (-10..0).each do |number|
7
+ CousinRoman::Arabian.valid?(number).should be_false
8
+ end
9
+ end
10
+
11
+ it 'should consider valid numbers > 1 and <= 3999' do
12
+ CousinRoman::Arabian.valid?(1).should be_true
13
+ CousinRoman::Arabian.valid?(3999).should be_true
14
+ end
15
+
16
+ it 'should consider invalid numbers > 3999' do
17
+ CousinRoman::Arabian.valid?(4000).should be_false
18
+ end
19
+ end
20
+
21
+
22
+ describe 'convert' do
23
+ 1.upto(3999).each do |arabian|
24
+ it "should succeed on #{arabian}", slow: true do
25
+ roman = CousinRoman::Arabian.convert(arabian)
26
+ CousinRoman::Roman.valid?(roman).should be_true
27
+ CousinRoman::Roman.convert(roman).should == arabian
28
+ end
29
+ end
30
+ end
31
+
32
+ describe 'to_roman' do
33
+ it 'should call convert on valid number' do
34
+ CousinRoman::Arabian.should_receive(:convert).and_call_original
35
+ CousinRoman::Arabian.to_roman(1).should == 'I'
36
+ end
37
+
38
+ it 'should return nil on invalid number' do
39
+ CousinRoman::Arabian.to_roman(100500).should be_nil
40
+ end
41
+ end
42
+
43
+ describe 'to_roman!' do
44
+ it 'should call convert on valid number' do
45
+ CousinRoman::Arabian.should_receive(:convert).and_call_original
46
+ CousinRoman::Arabian.to_roman!(1).should == 'I'
47
+ end
48
+
49
+ it 'should throw TypeError on invalid number' do
50
+ expect { CousinRoman::Arabian.to_roman!(100500) }.to raise_error(TypeError)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe CousinRoman::Roman do
4
+ describe 'valid?' do
5
+ describe 'literals validation' do
6
+ ASCII = 0.upto(127).map(&:chr)
7
+ NON_ROMAN_LITERALS = ASCII - CousinRoman::LITERALS
8
+
9
+ CousinRoman::LITERALS.each do |l|
10
+ it "should allow #{l}" do
11
+ CousinRoman::Roman.valid?(l).should be_true
12
+ end
13
+ end
14
+
15
+ NON_ROMAN_LITERALS.each do |l|
16
+ it "should not allow #{l}" do
17
+ CousinRoman::Roman.valid?(l).should be_false
18
+ end
19
+ end
20
+
21
+ it 'should not allow mix of allowed and disallowed literals' do
22
+ CousinRoman::Roman.valid?('MYCXI').should be_false
23
+ end
24
+
25
+ it 'should not allow empty string' do
26
+ CousinRoman::Roman.valid?('').should be_false
27
+ end
28
+ end
29
+
30
+ describe 'factors validation' do
31
+ CousinRoman::ONES.keys.each do |factor|
32
+ 1.upto(3).each do |reps|
33
+ it "should allow #{reps} repetitions of #{factor}" do
34
+ CousinRoman::Roman.valid?(factor*reps).should be_true
35
+ end
36
+ end
37
+
38
+ it "should not allow more than 3 repetitions of #{factor}" do
39
+ CousinRoman::Roman.valid?(factor*4).should be_false
40
+ end
41
+ end
42
+
43
+ CousinRoman::FIVES.merge(CousinRoman::SUBTRACTIVES).keys.each do |factor|
44
+ it "should not allow repetition of #{factor}" do
45
+ CousinRoman::Roman.valid?(factor*2).should be_false
46
+ end
47
+ end
48
+
49
+ it 'should allow ones and fives of the same power' do
50
+ CousinRoman::FIVES.keys.each_with_index do |five, index|
51
+ 1.upto(3).each do |reps|
52
+ corresponding_one = CousinRoman::ONES.keys[index]
53
+ CousinRoman::Roman.valid?(five + (corresponding_one * reps)).should be_true
54
+ end
55
+ end
56
+ end
57
+
58
+ it 'should not allow subtractives and ones or fives of the same power' do
59
+ CousinRoman::Roman.valid?('ivi').should be_false
60
+ CousinRoman::Roman.valid?('ixi').should be_false
61
+ CousinRoman::Roman.valid?('xlx').should be_false
62
+ CousinRoman::Roman.valid?('xcx').should be_false
63
+ CousinRoman::Roman.valid?('cdc').should be_false
64
+ CousinRoman::Roman.valid?('cmc').should be_false
65
+
66
+ CousinRoman::Roman.valid?('ivv').should be_false
67
+ CousinRoman::Roman.valid?('ixv').should be_false
68
+ CousinRoman::Roman.valid?('xll').should be_false
69
+ CousinRoman::Roman.valid?('xcl').should be_false
70
+ CousinRoman::Roman.valid?('cdd').should be_false
71
+ CousinRoman::Roman.valid?('cmd').should be_false
72
+ end
73
+ end
74
+
75
+ describe 'ordering validation' do
76
+ context 'when validating that factors are ordered by descreasing of power' do
77
+ ORDERINGS_RIGHT = [
78
+ 'md', 'mc',
79
+ 'cl', 'cx',
80
+ 'xv', 'xi',
81
+ 'mcm', 'mcd',
82
+ 'cxc', 'cxl',
83
+ 'xix', 'xiv'
84
+ ]
85
+ ORDERINGS_WRONG = [
86
+ 'dm', 'lc', 'vx',
87
+ 'cmm', 'cdm',
88
+ 'xcc', 'xlc',
89
+ 'ixx', 'ivx'
90
+ ]
91
+
92
+ ORDERINGS_RIGHT.each do |pair|
93
+ high, low = pair.split('', 2)
94
+ it "should allow #{high}#{low}" do
95
+ CousinRoman::Roman.valid?(high + low).should be_true
96
+ end
97
+ end
98
+
99
+ ORDERINGS_WRONG.each do |pair|
100
+ low, high = pair.split('', 2)
101
+ it "should not allow #{low}#{high}" do
102
+ CousinRoman::Roman.valid?(low + high).should be_false
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ describe 'convert' do
110
+ context 'singular factors' do
111
+ CousinRoman::FACTORS.each do |factor, number|
112
+ it "should convert #{factor} to #{number}" do
113
+ CousinRoman::Roman.convert(factor).should == number
114
+ end
115
+ end
116
+ end
117
+
118
+ context 'repetitive factors' do
119
+ CousinRoman::ONES.each do |factor, number|
120
+ 1.upto(3).each do |reps|
121
+ it "should convert #{factor*reps} to #{number*reps}" do
122
+ CousinRoman::Roman.convert(factor*reps).should == (number*reps)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'different power factors' do
129
+ it 'should honor ones' do
130
+ CousinRoman::Roman.convert('mcxi').should == 1111
131
+ end
132
+
133
+ it 'should honor fives' do
134
+ CousinRoman::Roman.convert('dlv').should == 555
135
+ end
136
+
137
+ it 'should honor ones and fives together' do
138
+ CousinRoman::Roman.convert('mdclxvi').should == 1666
139
+ end
140
+
141
+ it 'should honor subtractives ones and fives together' do
142
+ CousinRoman::Roman.convert('mcmlxxxix').should == 1989
143
+ end
144
+
145
+ it 'should honor max number' do
146
+ CousinRoman::Roman.convert('mmmcmxcix').should == 3999
147
+ end
148
+
149
+ it 'should honor the longest number' do
150
+ CousinRoman::Roman.convert('dccclxxxviii').should == 888
151
+ end
152
+
153
+ it 'should be case insensitive' do
154
+ number = 'MCXI'
155
+ CousinRoman::Roman.convert(number).should == CousinRoman::Roman.convert(number.downcase)
156
+ end
157
+ end
158
+ end
159
+
160
+ describe 'to_arabian' do
161
+ it 'should call convert on valid number' do
162
+ CousinRoman::Roman.should_receive(:convert).and_call_original
163
+ CousinRoman::Roman.to_arabian('MMM').should == 3000
164
+ end
165
+
166
+ it 'should return nil on invalid number' do
167
+ CousinRoman::Roman.to_arabian('YRU?!').should be_nil
168
+ end
169
+ end
170
+
171
+ describe 'to_arabian!' do
172
+ it 'should call convert on valid number' do
173
+ CousinRoman::Roman.should_receive(:convert).and_call_original
174
+ CousinRoman::Roman.to_arabian!('MMM').should == 3000
175
+ end
176
+
177
+ it 'should throw TypeError on invalid number' do
178
+ expect { CousinRoman::Roman.to_arabian!('YRU?!') }.to raise_error(TypeError)
179
+ end
180
+ end
181
+
182
+ end
@@ -4,195 +4,26 @@ describe CousinRoman do
4
4
  it 'should have a version number' do
5
5
  CousinRoman::VERSION.should_not be_nil
6
6
  end
7
-
8
- describe 'valid?' do
9
- describe 'literals validation' do
10
- ASCII = 0.upto(127).map(&:chr)
11
- NON_ROMAN_LITERALS = ASCII - CousinRoman::LITERALS
12
-
13
- CousinRoman::LITERALS.each do |l|
14
- it "should allow #{l}" do
15
- CousinRoman.valid?(l).should be_true
16
- end
17
- end
18
-
19
- NON_ROMAN_LITERALS.each do |l|
20
- it "should not allow #{l}" do
21
- CousinRoman.valid?(l).should be_false
22
- end
23
- end
24
-
25
- it 'should not allow mix of allowed and disallowed literals' do
26
- CousinRoman.valid?('MYCXI').should be_false
27
- end
28
-
29
- it 'should not allow empty string' do
30
- CousinRoman.valid?('').should be_false
31
- end
32
- end
33
-
34
- describe 'factors validation' do
35
- CousinRoman::ONES.keys.each do |factor|
36
- 1.upto(3).each do |reps|
37
- it "should allow #{reps} repetitions of #{factor}" do
38
- CousinRoman.valid?(factor*reps).should be_true
39
- end
40
- end
41
-
42
- it "should not allow more than 3 repetitions of #{factor}" do
43
- CousinRoman.valid?(factor*4).should be_false
44
- end
45
- end
46
-
47
- CousinRoman::FIVES.merge(CousinRoman::SUBTRACTIVE).keys.each do |factor|
48
- it "should not allow repetition of #{factor}" do
49
- CousinRoman.valid?(factor*2).should be_false
50
- end
51
- end
52
-
53
- it 'should allow ones and fives of the same power' do
54
- CousinRoman::FIVES.keys.each_with_index do |five, index|
55
- 1.upto(3).each do |reps|
56
- corresponding_one = CousinRoman::ONES.keys[index]
57
- CousinRoman.valid?(five + (corresponding_one * reps)).should be_true
58
- end
59
- end
60
- end
61
-
62
- it 'should not allow subtractives and ones or fives of the same power' do
63
- CousinRoman.valid?('ivi').should be_false
64
- CousinRoman.valid?('ixi').should be_false
65
- CousinRoman.valid?('xlx').should be_false
66
- CousinRoman.valid?('xcx').should be_false
67
- CousinRoman.valid?('cdc').should be_false
68
- CousinRoman.valid?('cmc').should be_false
69
-
70
- CousinRoman.valid?('ivv').should be_false
71
- CousinRoman.valid?('ixv').should be_false
72
- CousinRoman.valid?('xll').should be_false
73
- CousinRoman.valid?('xcl').should be_false
74
- CousinRoman.valid?('cdd').should be_false
75
- CousinRoman.valid?('cmd').should be_false
76
- end
77
- end
78
-
79
- describe 'ordering validation' do
80
- context 'when validating that factors are ordered by descreasing of power' do
81
- ORDERINGS_RIGHT = [
82
- 'md', 'mc',
83
- 'cl', 'cx',
84
- 'xv', 'xi',
85
- 'mcm', 'mcd',
86
- 'cxc', 'cxl',
87
- 'xix', 'xiv'
88
- ]
89
- ORDERINGS_WRONG = [
90
- 'dm', 'lc', 'vx',
91
- 'cmm', 'cdm',
92
- 'xcc', 'xlc',
93
- 'ixx', 'ivx'
94
- ]
95
-
96
- ORDERINGS_RIGHT.each do |pair|
97
- high, low = pair.split('', 2)
98
- it "should allow #{high}#{low}" do
99
- CousinRoman.valid?(high + low).should be_true
100
- end
101
- end
102
-
103
- ORDERINGS_WRONG.each do |pair|
104
- low, high = pair.split('', 2)
105
- it "should not allow #{low}#{high}" do
106
- CousinRoman.valid?(low + high).should be_false
107
- end
108
- end
109
- end
110
- end
111
- end
112
-
113
- describe 'convert' do
114
- context 'singular factors' do
115
- CousinRoman::FACTORS.each do |factor, number|
116
- it "should convert #{factor} to #{number}" do
117
- CousinRoman.convert(factor).should == number
118
- end
119
- end
120
- end
121
-
122
- context 'repetitive factors' do
123
- CousinRoman::ONES.each do |factor, number|
124
- 1.upto(3).each do |reps|
125
- it "should convert #{factor*reps} to #{number*reps}" do
126
- CousinRoman.convert(factor*reps).should == (number*reps)
127
- end
128
- end
129
- end
130
- end
131
-
132
- context 'different power factors' do
133
- it 'should honor ones' do
134
- CousinRoman.convert('mcxi').should == 1111
135
- end
136
-
137
- it 'should honor fives' do
138
- CousinRoman.convert('dlv').should == 555
139
- end
140
-
141
- it 'should honor ones and fives together' do
142
- CousinRoman.convert('mdclxvi').should == 1666
143
- end
144
-
145
- it 'should honor subtractives ones and fives together' do
146
- CousinRoman.convert('mcmlxxxix').should == 1989
147
- end
148
-
149
- it 'should honor max number' do
150
- CousinRoman.convert('mmmcmxcix').should == 3999
151
- end
152
-
153
- it 'should honor the longest number' do
154
- CousinRoman.convert('dccclxxxviii').should == 888
155
- end
156
-
157
- it 'should be case insensitive' do
158
- number = 'MCXI'
159
- CousinRoman.convert(number).should == CousinRoman.convert(number.downcase)
160
- end
161
- end
162
- end
163
-
164
- describe 'to_arabic' do
165
- it 'should call convert on valid number' do
166
- CousinRoman.should_receive(:convert).and_call_original
167
- CousinRoman.to_arabic('MMM').should == 3000
168
- end
169
-
170
- it 'should return nil on invalid number' do
171
- CousinRoman.to_arabic('YRU?!').should be_nil
172
- end
173
- end
174
-
175
- describe 'to_arabic!' do
176
- it 'should call convert on valid number' do
177
- CousinRoman.should_receive(:convert).and_call_original
178
- CousinRoman.to_arabic!('MMM').should == 3000
179
- end
180
-
181
- it 'should throw TypeError on invalid number' do
182
- expect { CousinRoman.to_arabic!('YRU?!') }.to raise_error(TypeError)
183
- end
184
- end
185
-
186
7
  end
187
8
 
188
9
  describe String do
189
- [:to_arabic, :to_arabic!].each do |meth|
10
+ [:to_arabian, :to_arabian!].each do |meth|
190
11
  it { should respond_to(meth) }
191
12
 
192
- it "should call CousinRoman.#{meth} on String##{meth}" do
13
+ it "should call CousinRoman::Roman.#{meth} on String##{meth}" do
193
14
  roman = 'i'
194
- CousinRoman.should_receive(meth).with(roman).and_call_original
15
+ CousinRoman::Roman.should_receive(meth).with(roman).and_call_original
195
16
  roman.send(meth).should == 1
196
17
  end
197
18
  end
198
19
  end
20
+
21
+ describe Integer do
22
+ [:to_roman, :to_roman!].each do |meth|
23
+ it "should call CousinRoman::Arabian.#{meth} on Fixnum##{meth}" do
24
+ arabian = 1
25
+ CousinRoman::Arabian.should_receive(meth).with(arabian).and_call_original
26
+ arabian.send(meth).should == 'I'
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cousin_roman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Pyanykh
@@ -52,8 +52,8 @@ dependencies:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: Easily convert Roman numerals to Integers. Functionality provided via
56
- String extension
55
+ description: Easily convert Roman and Arabian number. Functionality provided via String
56
+ and extensions
57
57
  email:
58
58
  - artem.pyanykh@gmail.com
59
59
  executables: []
@@ -69,9 +69,13 @@ files:
69
69
  - Rakefile
70
70
  - cousin_roman.gemspec
71
71
  - lib/cousin_roman.rb
72
- - lib/cousin_roman/conversion.rb
72
+ - lib/cousin_roman/arabian.rb
73
+ - lib/cousin_roman/integer_extension.rb
74
+ - lib/cousin_roman/roman.rb
73
75
  - lib/cousin_roman/string_extension.rb
74
76
  - lib/cousin_roman/version.rb
77
+ - spec/cousin_roman/arabian_spec.rb
78
+ - spec/cousin_roman/roman_spec.rb
75
79
  - spec/cousin_roman_spec.rb
76
80
  - spec/spec_helper.rb
77
81
  homepage: https://github.com/ArtemPyanykh/cousin_roman
@@ -97,7 +101,9 @@ rubyforge_project:
97
101
  rubygems_version: 2.1.8
98
102
  signing_key:
99
103
  specification_version: 4
100
- summary: Convert Roman numerals to Integers
104
+ summary: Convert Roman numerals to Integers and vice versa
101
105
  test_files:
106
+ - spec/cousin_roman/arabian_spec.rb
107
+ - spec/cousin_roman/roman_spec.rb
102
108
  - spec/cousin_roman_spec.rb
103
109
  - spec/spec_helper.rb