roman_numbers 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/autotest/discover.rb +2 -0
- data/lib/roman_numbers.rb +29 -0
- data/lib/roman_numbers/roman_number.rb +166 -0
- data/lib/roman_numbers/version.rb +3 -0
- data/roman_numbers.gemspec +27 -0
- data/spec/roman_numbers/roman_number_spec.rb +252 -0
- data/spec/spec_helper.rb +14 -0
- metadata +143 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6daa393f9570d95a67b67cd1a84a135998311b4b
|
4
|
+
data.tar.gz: 60cc1370d2fc105f826ad919e2338c20078db105
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3033cdc3ec59fd57255b2c13534c5f418c36a7874d0cb53e81e7f19f098aa4887af93cdba16ab19c0773ea71c4b7618c49168c5a204fc29e747889e6d9a9db97
|
7
|
+
data.tar.gz: 222fc3d1e1555efc9f1384db184c8097885204d510971d19993f6a7453a2a2db25502c457e8542289d77f6b5d3dea47f70d76ad73aef776193a7a642ce7790e7
|
data/.gitignore
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
|
19
|
+
# Ignore RubyMine's .idea directory
|
20
|
+
/.idea/*
|
21
|
+
|
22
|
+
# Ignore Aptana's .project file
|
23
|
+
/.project
|
24
|
+
|
25
|
+
# Ignoring .rvmrc
|
26
|
+
/.rvmrc
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 G580 mgoyal
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# RomanNumbers
|
2
|
+
|
3
|
+
Conversion between Integers and Roman Numbers
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'roman_numbers'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install roman_numbers
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Some Examples:
|
22
|
+
|
23
|
+
> RomanNumbers::RomanNumber.new(3999).convert_decimal_to_roman
|
24
|
+
"MMMCMXCIX"
|
25
|
+
|
26
|
+
> RomanNumbers::RomanNumber.new('MMMCMXCIX').convert_roman_to_decimal
|
27
|
+
3999
|
28
|
+
|
29
|
+
> 'MCMXLIV'.from_roman_to_integer
|
30
|
+
1944
|
31
|
+
|
32
|
+
> 1944.to_roman
|
33
|
+
"MCMXLIV"
|
34
|
+
|
35
|
+
> 'MMMMMX'.from_roman_to_integer
|
36
|
+
RomanNumbers::InvalidInputError
|
37
|
+
|
38
|
+
> 999383.to_roman
|
39
|
+
RomanNumbers::InvalidInputError
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it
|
44
|
+
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
|
47
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
48
|
+
|
49
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
50
|
+
|
51
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'roman_numbers/version'
|
2
|
+
require 'roman_numbers/roman_number'
|
3
|
+
|
4
|
+
module RomanNumbers
|
5
|
+
# custom Exceptions
|
6
|
+
class Error < StandardError;
|
7
|
+
end
|
8
|
+
class StartsWithNonRepeatableRomanUnitError < Error;
|
9
|
+
end
|
10
|
+
class NonReachableCodeError < Error;
|
11
|
+
end
|
12
|
+
class InvalidInputError < Error;
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# opening String class to add from_roman_to_integer method
|
17
|
+
class String
|
18
|
+
def from_roman_to_integer
|
19
|
+
RomanNumbers::RomanNumber.new(self).convert_roman_to_decimal
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# opening Integer class to add from_integer_to_roman method
|
24
|
+
class Integer
|
25
|
+
def to_roman
|
26
|
+
RomanNumbers::RomanNumber.new(self).convert_decimal_to_roman
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'roman_numbers/version'
|
2
|
+
|
3
|
+
module RomanNumbers
|
4
|
+
class RomanNumber
|
5
|
+
|
6
|
+
ROMAN_REPEATABLE_UNITS = [
|
7
|
+
{:unit => :M, :value => 1000}, # element first
|
8
|
+
{:unit => :C, :value => 100},
|
9
|
+
{:unit => :X, :value => 10},
|
10
|
+
{:unit => :I, :value => 1} # element last
|
11
|
+
].sort { |x, y| y[:value] <=> x[:value] }
|
12
|
+
|
13
|
+
ROMAN_NON_REPEATABLE_UNITS_1 = [
|
14
|
+
{:unit => :D, :value => 500}, # element first
|
15
|
+
{:unit => :L, :value => 50},
|
16
|
+
{:unit => :V, :value => 5}, # element last
|
17
|
+
].sort { |x, y| y[:value] <=> x[:value] }
|
18
|
+
|
19
|
+
ROMAN_NON_REPEATABLE_UNITS_2 = [
|
20
|
+
{:unit => :CM, :value => 900}, # element first
|
21
|
+
{:unit => :CD, :value => 400},
|
22
|
+
{:unit => :XC, :value => 90},
|
23
|
+
{:unit => :XL, :value => 40},
|
24
|
+
{:unit => :IX, :value => 9},
|
25
|
+
{:unit => :IV, :value => 4} # element last
|
26
|
+
].sort { |x, y| y[:value] <=> x[:value] }
|
27
|
+
|
28
|
+
ROMAN_NON_REPEATABLE_UNITS = (ROMAN_NON_REPEATABLE_UNITS_1 + ROMAN_NON_REPEATABLE_UNITS_2).sort { |x, y| y[:value] <=> x[:value] }
|
29
|
+
ROMAN_DOUBLE_UNITS = ROMAN_NON_REPEATABLE_UNITS_2.sort { |x, y| y[:value] <=> x[:value] }
|
30
|
+
ROMAN_SINGLE_UNITS = (ROMAN_NON_REPEATABLE_UNITS_1 + ROMAN_REPEATABLE_UNITS).sort { |x, y| y[:value] <=> x[:value] }
|
31
|
+
ROMAN_UNITS = (ROMAN_REPEATABLE_UNITS + ROMAN_NON_REPEATABLE_UNITS_1 + ROMAN_NON_REPEATABLE_UNITS_2).sort { |x, y| y[:value] <=> x[:value] }
|
32
|
+
|
33
|
+
# based on above non_repeatable units, allowed repetition is 3
|
34
|
+
MAX_ALLOWED_REPETITION = 3
|
35
|
+
|
36
|
+
# initializing element
|
37
|
+
def initialize(input)
|
38
|
+
# checking input type and setting instance variables
|
39
|
+
case input
|
40
|
+
when Integer
|
41
|
+
@input_integer = input
|
42
|
+
@staged_roman_hash = Array.new
|
43
|
+
@output_roman = String.new
|
44
|
+
when String
|
45
|
+
@input_string = input.upcase
|
46
|
+
@output_arabic = 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# converts arabic to roman
|
51
|
+
def convert_decimal_to_roman(input_integer=@input_integer)
|
52
|
+
# validating input
|
53
|
+
unless (1..3999).include? input_integer
|
54
|
+
raise InvalidInputError, "Invalid Input: #{input_integer}"
|
55
|
+
end
|
56
|
+
# getting staged roman hash
|
57
|
+
calculate_staged_roman_hash(input_integer)
|
58
|
+
# extracting hash from staged roman hash
|
59
|
+
@staged_roman_hash.each do |element|
|
60
|
+
@output_roman << (element[:largest_element][:unit].to_s)*(element[:times])
|
61
|
+
end
|
62
|
+
return @output_roman
|
63
|
+
end
|
64
|
+
|
65
|
+
# converts given arabic number (in string form) to corresponding integer
|
66
|
+
def convert_roman_to_decimal(input_roman=@input_string.clone)
|
67
|
+
input_roman
|
68
|
+
# generating regex expressions
|
69
|
+
double_units_array = ROMAN_NON_REPEATABLE_UNITS_2.map { |element| ('^' + element[:unit].to_s) }
|
70
|
+
single_units_array = (ROMAN_REPEATABLE_UNITS + ROMAN_NON_REPEATABLE_UNITS_1).map { |element| ('^' + element[:unit].to_s) }
|
71
|
+
double_units_regex = Regexp.new(double_units_array.join('|'))
|
72
|
+
single_units_regex = Regexp.new(single_units_array.join('|'))
|
73
|
+
# validation
|
74
|
+
# TODO: to add more validations
|
75
|
+
if input_roman =~ /(.)\1{#{MAX_ALLOWED_REPETITION},}/
|
76
|
+
raise InvalidInputError, "Invalid Input: #{input_roman}"
|
77
|
+
end
|
78
|
+
# processing
|
79
|
+
if input_roman.length > 0
|
80
|
+
if unit = input_roman.slice!(double_units_regex)
|
81
|
+
@output_arabic += ROMAN_DOUBLE_UNITS.find { |element| element[:unit] == unit.to_sym }[:value]
|
82
|
+
convert_roman_to_decimal(input_roman)
|
83
|
+
elsif unit = input_roman.slice!(single_units_regex)
|
84
|
+
@output_arabic += ROMAN_SINGLE_UNITS.find { |element| element[:unit] == unit.to_sym }[:value]
|
85
|
+
convert_roman_to_decimal(input_roman)
|
86
|
+
else
|
87
|
+
# invalud input
|
88
|
+
raise InvalidInputError, "Invalid Input: #{input_roman}"
|
89
|
+
end
|
90
|
+
else
|
91
|
+
# process is complete
|
92
|
+
return @output_arabic
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
# returns an array of hashed containing info on desired output roman
|
98
|
+
def calculate_staged_roman_hash(input_integer)
|
99
|
+
begin
|
100
|
+
temp_hash = largest_repeatable_element(input_integer)
|
101
|
+
rescue StartsWithNonRepeatableRomanUnitError => ex
|
102
|
+
temp_hash = largest_non_repeatable_element(input_integer)
|
103
|
+
end
|
104
|
+
if temp_hash
|
105
|
+
@staged_roman_hash << temp_hash
|
106
|
+
input_integer = temp_hash[:reduced_integer]
|
107
|
+
calculate_staged_roman_hash(input_integer)
|
108
|
+
else
|
109
|
+
# processing done
|
110
|
+
return @staged_roman_hash
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# returns reduced_integer, largest repeatable element, and number of times it can be repeated
|
115
|
+
def largest_repeatable_element(input_integer)
|
116
|
+
if input_integer > 0
|
117
|
+
largest_element = ROMAN_REPEATABLE_UNITS.find { |element| input_integer >= element[:value] }
|
118
|
+
# TODO: make it efficient by removing elements before largest_element
|
119
|
+
# TODO: to use binary search instead
|
120
|
+
if largest_element
|
121
|
+
times = input_integer/largest_element[:value]
|
122
|
+
reduced_integer = input_integer%largest_element[:value]
|
123
|
+
if times > MAX_ALLOWED_REPETITION
|
124
|
+
# given integer starts with non_repeatable roman unit
|
125
|
+
raise StartsWithNonRepeatableRomanUnitError
|
126
|
+
end
|
127
|
+
return {:reduced_integer => reduced_integer, :largest_element => largest_element, :times => times}
|
128
|
+
else
|
129
|
+
# non-reachable code
|
130
|
+
raise NonReachableCodeError, 'LargestElementIsNil'
|
131
|
+
end
|
132
|
+
elsif input_integer == 0
|
133
|
+
# process completed
|
134
|
+
return nil
|
135
|
+
else
|
136
|
+
# non-reachable code
|
137
|
+
# input_integer has to be >=0
|
138
|
+
raise NonReachableCodeError, 'ReceivedNegativeInteger'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# returns largest non-repeatable element
|
143
|
+
def largest_non_repeatable_element(input_integer)
|
144
|
+
if input_integer > 0
|
145
|
+
largest_element = ROMAN_NON_REPEATABLE_UNITS.find { |element| input_integer >= element[:value] }
|
146
|
+
# TODO: make it efficient by removing elements before largest_element
|
147
|
+
# TODO: to use binary search instead
|
148
|
+
if largest_element
|
149
|
+
reduced_integer = input_integer%largest_element[:value]
|
150
|
+
return {:reduced_integer => reduced_integer, :largest_element => largest_element, :times => 1}
|
151
|
+
else
|
152
|
+
# no non_repeatable element preset, but process is not complete yet
|
153
|
+
return {:reduced_integer => input_integer, :largest_element => nil, :times => 0}
|
154
|
+
end
|
155
|
+
elsif input_integer == 0
|
156
|
+
# process completed
|
157
|
+
return nil
|
158
|
+
else
|
159
|
+
# non-reachable code
|
160
|
+
# input_integer has to be >=0
|
161
|
+
raise NonReachableCodeError, 'ReceivedNegativeInteger'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'roman_numbers/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "roman_numbers"
|
8
|
+
spec.version = RomanNumbers::VERSION
|
9
|
+
spec.authors = ["Munish Goyal"]
|
10
|
+
spec.email = ["munishapc@gmail.com"]
|
11
|
+
spec.description = %q{Conversion between Integers and Roman Numbers}
|
12
|
+
spec.summary = %q{Conversion between Integers and Roman Numbers}
|
13
|
+
spec.homepage = "https://github.com/goyalmunish/roman_numbers"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", ">= 1.3"
|
22
|
+
spec.add_development_dependency "rake", ">= 0.9"
|
23
|
+
spec.add_development_dependency "awesome_print", ">= 1.2"
|
24
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
25
|
+
spec.add_development_dependency "autotest"
|
26
|
+
spec.add_development_dependency "simplecov"
|
27
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module RomanNumbers
|
4
|
+
describe RomanNumber do # EXAMPLE GROUP
|
5
|
+
before(:each) do
|
6
|
+
@roman_number = RomanNumber.new(1)
|
7
|
+
end
|
8
|
+
describe '#largest_repeatable_element' do
|
9
|
+
it 'works for "3999" as input' do
|
10
|
+
output = @roman_number.largest_repeatable_element(3999)
|
11
|
+
output.should == {:reduced_integer => 999, :largest_element => {:unit => :M, :value => 1000}, :times => 3}
|
12
|
+
end
|
13
|
+
it 'works for "1066" as input' do
|
14
|
+
output = @roman_number.largest_repeatable_element(1066)
|
15
|
+
output.should == {:reduced_integer => 66, :largest_element => {:unit => :M, :value => 1000}, :times => 1}
|
16
|
+
end
|
17
|
+
it 'works for "207" as input' do
|
18
|
+
output = @roman_number.largest_repeatable_element(207)
|
19
|
+
output.should == {:reduced_integer => 7, :largest_element => {:unit => :C, :value => 100}, :times => 2}
|
20
|
+
end
|
21
|
+
it 'works for "10" as input' do
|
22
|
+
output = @roman_number.largest_repeatable_element(10)
|
23
|
+
output.should == {:reduced_integer => 0, :largest_element => {:unit => :X, :value => 10}, :times => 1}
|
24
|
+
end
|
25
|
+
it 'raises StartsWithNonRepeatableRomanUnitError for 999 as input' do
|
26
|
+
expect {
|
27
|
+
@roman_number.largest_repeatable_element(999)
|
28
|
+
}.to raise_error(StartsWithNonRepeatableRomanUnitError)
|
29
|
+
end
|
30
|
+
it 'raises StartsWithNonRepeatableRomanUnitError for 44 as input' do
|
31
|
+
expect {
|
32
|
+
@roman_number.largest_repeatable_element(44)
|
33
|
+
}.to raise_error(StartsWithNonRepeatableRomanUnitError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#largest_non_repeatable_element' do
|
38
|
+
before(:each) do
|
39
|
+
@roman_number = RomanNumber.new(1)
|
40
|
+
end
|
41
|
+
it 'works for "999" as input' do
|
42
|
+
output = @roman_number.largest_non_repeatable_element(999)
|
43
|
+
output.should == {:reduced_integer => 99, :largest_element => {:unit => :CM, :value => 900}, :times => 1}
|
44
|
+
end
|
45
|
+
it 'works for "900" as input' do
|
46
|
+
output = @roman_number.largest_non_repeatable_element(900)
|
47
|
+
output.should == {:reduced_integer => 0, :largest_element => {:unit => :CM, :value => 900}, :times => 1}
|
48
|
+
end
|
49
|
+
it 'works for "44" as input' do
|
50
|
+
output = @roman_number.largest_non_repeatable_element(44)
|
51
|
+
output.should == {:reduced_integer => 4, :largest_element => {:unit => :XL, :value => 40}, :times => 1}
|
52
|
+
end
|
53
|
+
it 'works for "49" as input' do
|
54
|
+
output = @roman_number.largest_non_repeatable_element(49)
|
55
|
+
output.should == {:reduced_integer => 9, :largest_element => {:unit => :XL, :value => 40}, :times => 1}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#convert_arabic_to_roman' do
|
60
|
+
context 'For Very Simple Integers' do
|
61
|
+
it 'returns I for 1' do
|
62
|
+
RomanNumber.new(1).convert_decimal_to_roman.should == 'I'
|
63
|
+
end
|
64
|
+
it 'returns V for 5' do
|
65
|
+
RomanNumber.new(5).convert_decimal_to_roman.should == 'V'
|
66
|
+
end
|
67
|
+
it 'returns X for 10' do
|
68
|
+
RomanNumber.new(10).convert_decimal_to_roman.should == 'X'
|
69
|
+
end
|
70
|
+
it 'returns L for 50' do
|
71
|
+
RomanNumber.new(50).convert_decimal_to_roman.should == 'L'
|
72
|
+
end
|
73
|
+
it 'returns C for 100' do
|
74
|
+
RomanNumber.new(100).convert_decimal_to_roman.should == 'C'
|
75
|
+
end
|
76
|
+
it 'returns D for 500' do
|
77
|
+
RomanNumber.new(500).convert_decimal_to_roman.should == 'D'
|
78
|
+
end
|
79
|
+
it 'returns M for 1000' do
|
80
|
+
RomanNumber.new(1000).convert_decimal_to_roman.should == 'M'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
context 'For Simple Integers' do
|
84
|
+
it 'returns IV for 4' do
|
85
|
+
RomanNumber.new(4).convert_decimal_to_roman.should == 'IV'
|
86
|
+
end
|
87
|
+
it 'returns IX for 9' do
|
88
|
+
RomanNumber.new(9).convert_decimal_to_roman.should == 'IX'
|
89
|
+
end
|
90
|
+
it 'returns XL for 40' do
|
91
|
+
RomanNumber.new(40).convert_decimal_to_roman.should == 'XL'
|
92
|
+
end
|
93
|
+
it 'returns XC for 90' do
|
94
|
+
RomanNumber.new(90).convert_decimal_to_roman.should == 'XC'
|
95
|
+
end
|
96
|
+
it 'returns CD for 400' do
|
97
|
+
RomanNumber.new(400).convert_decimal_to_roman.should == 'CD'
|
98
|
+
end
|
99
|
+
it 'returns CM for 900' do
|
100
|
+
RomanNumber.new(900).convert_decimal_to_roman.should == 'CM'
|
101
|
+
end
|
102
|
+
it 'returns CCVII for 207' do
|
103
|
+
RomanNumber.new(207).convert_decimal_to_roman.should == 'CCVII'
|
104
|
+
end
|
105
|
+
it 'returns MLXVI for 1066' do
|
106
|
+
RomanNumber.new(1066).convert_decimal_to_roman.should == 'MLXVI'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
context 'For Complex Integers' do
|
110
|
+
it 'returns XLIV for 44' do
|
111
|
+
RomanNumber.new(44).convert_decimal_to_roman.should == 'XLIV'
|
112
|
+
end
|
113
|
+
it 'returns XLIX for 49' do
|
114
|
+
RomanNumber.new(49).convert_decimal_to_roman.should == 'XLIX'
|
115
|
+
end
|
116
|
+
it 'returns CMIV for 904' do
|
117
|
+
RomanNumber.new(904).convert_decimal_to_roman.should == 'CMIV'
|
118
|
+
end
|
119
|
+
it 'returns CMXLIV for 944' do
|
120
|
+
RomanNumber.new(944).convert_decimal_to_roman.should == 'CMXLIV'
|
121
|
+
end
|
122
|
+
it 'returns MCMIV for 1904' do
|
123
|
+
RomanNumber.new(1904).convert_decimal_to_roman.should == 'MCMIV'
|
124
|
+
end
|
125
|
+
it 'returns MCMXLIV for 1944' do
|
126
|
+
RomanNumber.new(1944).convert_decimal_to_roman.should == 'MCMXLIV'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
context 'For Very Simple Integers' do
|
130
|
+
it 'returns MMMCMXCIX for 3999' do
|
131
|
+
RomanNumber.new(3999).convert_decimal_to_roman.should == 'MMMCMXCIX'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
context 'For Invalid Input' do
|
135
|
+
it 'raises InvalidInputError for 4000 as input' do
|
136
|
+
expect {
|
137
|
+
RomanNumber.new(4000).convert_decimal_to_roman
|
138
|
+
}.to raise_error(InvalidInputError)
|
139
|
+
end
|
140
|
+
it 'raises InvalidInputError for 0 as input' do
|
141
|
+
expect {
|
142
|
+
RomanNumber.new(0).convert_decimal_to_roman
|
143
|
+
}.to raise_error(InvalidInputError)
|
144
|
+
end
|
145
|
+
it 'raises InvalidInputError for -10 as input' do
|
146
|
+
expect {
|
147
|
+
RomanNumber.new(-10).convert_decimal_to_roman
|
148
|
+
}.to raise_error(InvalidInputError)
|
149
|
+
end
|
150
|
+
it 'raises InvalidInputError for "10" as input' do
|
151
|
+
expect {
|
152
|
+
RomanNumber.new('10').convert_decimal_to_roman
|
153
|
+
}.to raise_error(InvalidInputError)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#convert_roman_to_arabic' do
|
159
|
+
context 'For Simple Romans' do
|
160
|
+
it 'returns 1 for I' do
|
161
|
+
RomanNumber.new('I').convert_roman_to_decimal.should == 1
|
162
|
+
end
|
163
|
+
it 'returns 5 for V' do
|
164
|
+
RomanNumber.new('V').convert_roman_to_decimal.should == 5
|
165
|
+
end
|
166
|
+
it 'returns 10 for X' do
|
167
|
+
RomanNumber.new('X').convert_roman_to_decimal.should == 10
|
168
|
+
end
|
169
|
+
it 'returns 50 for L' do
|
170
|
+
RomanNumber.new('L').convert_roman_to_decimal.should == 50
|
171
|
+
end
|
172
|
+
it 'returns 100 for C' do
|
173
|
+
RomanNumber.new('C').convert_roman_to_decimal.should == 100
|
174
|
+
end
|
175
|
+
it 'returns 500 for D' do
|
176
|
+
RomanNumber.new('D').convert_roman_to_decimal.should == 500
|
177
|
+
end
|
178
|
+
it 'returns 1000 for M' do
|
179
|
+
RomanNumber.new('M').convert_roman_to_decimal.should == 1000
|
180
|
+
end
|
181
|
+
it 'returns 4 for IV' do
|
182
|
+
RomanNumber.new('IV').convert_roman_to_decimal.should == 4
|
183
|
+
end
|
184
|
+
it 'returns 9 for IX' do
|
185
|
+
RomanNumber.new('IX').convert_roman_to_decimal.should == 9
|
186
|
+
end
|
187
|
+
it 'returns 40 for XL' do
|
188
|
+
RomanNumber.new('XL').convert_roman_to_decimal.should == 40
|
189
|
+
end
|
190
|
+
it 'returns 90 for XC' do
|
191
|
+
RomanNumber.new('XC').convert_roman_to_decimal.should == 90
|
192
|
+
end
|
193
|
+
it 'returns 400 for CD' do
|
194
|
+
RomanNumber.new('CD').convert_roman_to_decimal.should == 400
|
195
|
+
end
|
196
|
+
it 'returns 900 for CM' do
|
197
|
+
RomanNumber.new('CM').convert_roman_to_decimal.should == 900
|
198
|
+
end
|
199
|
+
end
|
200
|
+
context 'For Complex Romans' do
|
201
|
+
it 'returns 207 for CCVII' do
|
202
|
+
RomanNumber.new('CCVII').convert_roman_to_decimal.should == 207
|
203
|
+
end
|
204
|
+
it 'returns 1066 for MLXVI' do
|
205
|
+
RomanNumber.new('MLXVI').convert_roman_to_decimal.should == 1066
|
206
|
+
end
|
207
|
+
it 'returns 44 for XLIV' do
|
208
|
+
RomanNumber.new('XLIV').convert_roman_to_decimal.should == 44
|
209
|
+
end
|
210
|
+
it 'returns 49 for XLIX' do
|
211
|
+
RomanNumber.new('XLIX').convert_roman_to_decimal.should == 49
|
212
|
+
end
|
213
|
+
it 'returns 904 for CMIV' do
|
214
|
+
RomanNumber.new('CMIV').convert_roman_to_decimal.should == 904
|
215
|
+
end
|
216
|
+
it 'returns 944 for CMXLIV' do
|
217
|
+
RomanNumber.new('CMXLIV').convert_roman_to_decimal.should == 944
|
218
|
+
end
|
219
|
+
it 'returns 1904 for MCMIV' do
|
220
|
+
RomanNumber.new('MCMIV').convert_roman_to_decimal.should == 1904
|
221
|
+
end
|
222
|
+
it 'returns 1944 for MCMXLIV' do
|
223
|
+
RomanNumber.new('MCMXLIV').convert_roman_to_decimal.should == 1944
|
224
|
+
end
|
225
|
+
it 'returns 30 for XXX' do
|
226
|
+
RomanNumber.new('XXX').convert_roman_to_decimal.should == 30
|
227
|
+
end
|
228
|
+
it 'returns 3999 for MMMCMXCIX' do
|
229
|
+
RomanNumber.new('MMMCMXCIX').convert_roman_to_decimal.should == 3999
|
230
|
+
end
|
231
|
+
end
|
232
|
+
context 'For Invalid Input' do
|
233
|
+
it 'raises InvalidInputError for ABCDE as input' do
|
234
|
+
expect {
|
235
|
+
RomanNumber.new('ABCDE').convert_roman_to_decimal
|
236
|
+
}.to raise_error(InvalidInputError)
|
237
|
+
end
|
238
|
+
it 'raises InvalidInputError for CCCCVII as input' do
|
239
|
+
expect {
|
240
|
+
RomanNumber.new('CCCCVII').convert_roman_to_decimal
|
241
|
+
}.to raise_error(InvalidInputError)
|
242
|
+
end
|
243
|
+
it 'raises InvalidInputError for CCVVVVI as input' do
|
244
|
+
expect {
|
245
|
+
RomanNumber.new('CCVVVVI').convert_roman_to_decimal
|
246
|
+
}.to raise_error(InvalidInputError)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# SimpleCov Settings
|
2
|
+
begin
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start
|
5
|
+
rescue LoadError
|
6
|
+
puts 'Coverage disabled, enable by installing simplecov'
|
7
|
+
end
|
8
|
+
|
9
|
+
# source
|
10
|
+
require_relative '../lib/roman_numbers'
|
11
|
+
|
12
|
+
# gems used
|
13
|
+
require 'rspec'
|
14
|
+
require 'awesome_print'
|
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roman_numbers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Munish Goyal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.9'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: awesome_print
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.14'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.14'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: autotest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Conversion between Integers and Roman Numbers
|
98
|
+
email:
|
99
|
+
- munishapc@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- .rspec
|
106
|
+
- Gemfile
|
107
|
+
- LICENSE.txt
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- autotest/discover.rb
|
111
|
+
- lib/roman_numbers.rb
|
112
|
+
- lib/roman_numbers/roman_number.rb
|
113
|
+
- lib/roman_numbers/version.rb
|
114
|
+
- roman_numbers.gemspec
|
115
|
+
- spec/roman_numbers/roman_number_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
homepage: https://github.com/goyalmunish/roman_numbers
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
metadata: {}
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 2.1.11
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Conversion between Integers and Roman Numbers
|
141
|
+
test_files:
|
142
|
+
- spec/roman_numbers/roman_number_spec.rb
|
143
|
+
- spec/spec_helper.rb
|