romaniac 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.travis.yml +12 -0
- data/Gemfile +2 -0
- data/LICENCE +19 -0
- data/README.md +160 -0
- data/Rakefile +9 -0
- data/VERSION +1 -0
- data/lib/romaniac.rb +88 -0
- data/lib/romaniac/const.rb +35 -0
- data/lib/romaniac/converter.rb +109 -0
- data/lib/romaniac/ext.rb +3 -0
- data/lib/romaniac/ext/enumerable.rb +14 -0
- data/lib/romaniac/ext/fixnum.rb +5 -0
- data/romaniac.gemspec +17 -0
- data/test/const_test.rb +10 -0
- data/test/ext/enumerable_test.rb +13 -0
- data/test/ext/fixnum_test.rb +28 -0
- data/test/helper.rb +7 -0
- data/test/romaniac_test.rb +155 -0
- metadata +98 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENCE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) MMXII Kyrylo Silin
|
2
|
+
|
3
|
+
This software is provided 'as-is', without any express or implied
|
4
|
+
warranty. In no event will the authors be held liable for any damages
|
5
|
+
arising from the use of this software.
|
6
|
+
|
7
|
+
Permission is granted to anyone to use this software for any purpose,
|
8
|
+
including commercial applications, and to alter it and redistribute it
|
9
|
+
freely, subject to the following restrictions:
|
10
|
+
|
11
|
+
1. The origin of this software must not be misrepresented; you must not
|
12
|
+
claim that you wrote the original software. If you use this software
|
13
|
+
in a product, an acknowledgment in the product documentation would be
|
14
|
+
appreciated but is not required.
|
15
|
+
|
16
|
+
2. Altered source versions must be plainly marked as such, and must not be
|
17
|
+
misrepresented as being the original software.
|
18
|
+
|
19
|
+
3. This notice may not be removed or altered from any source distribution.
|
data/README.md
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
Romaniac
|
2
|
+
![Romaniac][logo]
|
3
|
+
========
|
4
|
+
|
5
|
+
* Repository: [https://github.com/kyrylo/romaniac/][repo]
|
6
|
+
|
7
|
+
Description
|
8
|
+
-----------
|
9
|
+
|
10
|
+
Romaniac turns you into a Roman numerals maniac. Blimey, not really… But! At
|
11
|
+
at least you will be able to operate on some numbers.
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
15
|
+
|
16
|
+
gem install romaniac
|
17
|
+
|
18
|
+
Synopsis
|
19
|
+
--------
|
20
|
+
|
21
|
+
Basic example.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'romaniac'
|
25
|
+
|
26
|
+
ten = Roman(10) #=> (Roman: X)
|
27
|
+
twelve = Roman(12) #=> (Roman: XII)
|
28
|
+
puts ten.to_i #=> 10
|
29
|
+
|
30
|
+
# Also, you can use strings as arguments.
|
31
|
+
Roman('53') #=> (Roman: LIII)
|
32
|
+
Roman('4444') #=> ArgumentError: invalid value for Roman(): "4444"/
|
33
|
+
|
34
|
+
puts <<yummy
|
35
|
+
Hi!
|
36
|
+
My name is Kyrylo #{ Roman(1) }.
|
37
|
+
I have #{ Roman(3) } chocolate bars.
|
38
|
+
I just ate #{ Roman(2) } of them!
|
39
|
+
yummy
|
40
|
+
|
41
|
+
# Prints out:
|
42
|
+
Hi!
|
43
|
+
My name is Kyrylo I.
|
44
|
+
I have III chocolate bars.
|
45
|
+
I just ate II of them!
|
46
|
+
```
|
47
|
+
|
48
|
+
Arthmetic operations.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# Addition.
|
52
|
+
puts Roman(20) + Roman(5) #=> (Roman: XV)
|
53
|
+
|
54
|
+
# Subtraction.
|
55
|
+
Roman(20) - Roman(5) #=> (Roman: XV)
|
56
|
+
|
57
|
+
# Division.
|
58
|
+
puts Roman(20) / Roman(5) #=> (Roman: IV)
|
59
|
+
|
60
|
+
# Multiplication.
|
61
|
+
puts Roman(20) * Roman(5) #=> (Roman: C)
|
62
|
+
```
|
63
|
+
|
64
|
+
Comparison methods.
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Roman(20) > Roman(5) #=> true
|
68
|
+
Roman(20) < Roman(5) #=> false
|
69
|
+
Roman(20) == Roman(20) #=> true
|
70
|
+
```
|
71
|
+
|
72
|
+
If you feel brave enough, you can use monkey-patches.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
require 'romaniac/ext'
|
76
|
+
|
77
|
+
10.to_roman #=> X
|
78
|
+
|
79
|
+
# Enumerable goodness.
|
80
|
+
(:a..:c).each_with_roman_index.to_a
|
81
|
+
#=> [[:a, (Roman: I)], [:b, (Roman: II)], [:c, (Roman: III)]]
|
82
|
+
(:a..:c).map.with_roman_index(10).to_a
|
83
|
+
#=> [[:a, (Roman: X)], [:b, (Roman: XI)], [:c, (Roman: XII)]
|
84
|
+
```
|
85
|
+
|
86
|
+
If that is not enough for you, use Ruby constants as Roman numerals.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
require 'romaniac/const'
|
90
|
+
|
91
|
+
# Hrhr!
|
92
|
+
puts III + C #=> (Roman: CIII)
|
93
|
+
puts C / L #=> (Roman: II)
|
94
|
+
```
|
95
|
+
|
96
|
+
Pseudo real world example.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
# my_school_schedule.rb
|
100
|
+
require 'romaniac/ext'
|
101
|
+
|
102
|
+
puts 'TUESDAY', '-------'
|
103
|
+
{
|
104
|
+
'08:30' => '09:15',
|
105
|
+
'09:20' => '10:05',
|
106
|
+
'10:15' => '11:00',
|
107
|
+
'11:10' => '12:55',
|
108
|
+
'13:15' => '14:00',
|
109
|
+
'14:10' => '14:55',
|
110
|
+
'15:10' => '15:55'
|
111
|
+
}.each.with_roman_index do |(t_begin, t_end), index|
|
112
|
+
printf("%4s %5s - %5s\n", index, t_begin, t_end)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Will print out:
|
116
|
+
|
117
|
+
TUESDAY
|
118
|
+
-------
|
119
|
+
I 08:30 - 09:15
|
120
|
+
II 09:20 - 10:05
|
121
|
+
III 10:15 - 11:00
|
122
|
+
IV 11:10 - 12:55
|
123
|
+
V 13:15 - 14:00
|
124
|
+
VI 14:10 - 14:55
|
125
|
+
VII 15:10 - 15:55
|
126
|
+
```
|
127
|
+
|
128
|
+
Limitations
|
129
|
+
-----------
|
130
|
+
|
131
|
+
### Ruby implementations support
|
132
|
+
|
133
|
+
* MRI 1.8.7
|
134
|
+
* MRI 1.9.2
|
135
|
+
* MRI 1.9.3
|
136
|
+
* Latest REE
|
137
|
+
* JRuby 1.7.0
|
138
|
+
* Rubinius 1.2.4
|
139
|
+
|
140
|
+
Well, maybe in future (but screw it for now)
|
141
|
+
--------------------------------------------
|
142
|
+
|
143
|
+
Basically, these two features are intertwined.
|
144
|
+
|
145
|
+
* unicode support (so you can use Ⅷ or ⅷ instead of VIII);
|
146
|
+
* extended number limit (current limit is 3999, but can be extended up to
|
147
|
+
399999 with help of unicode).
|
148
|
+
|
149
|
+
Credits
|
150
|
+
-------
|
151
|
+
|
152
|
+
* Thanks to Jovanny Lemonad for Philosopher font;
|
153
|
+
|
154
|
+
Licence
|
155
|
+
-------
|
156
|
+
|
157
|
+
The project uses Zlib License. See LICENCE file for more information.
|
158
|
+
|
159
|
+
[logo]: http://img-fotki.yandex.ru/get/4138/98991937.f/0_8bb4e_ed3d7992_orig "Romaniac"
|
160
|
+
[repo]: https://github.com/kyrylo/romaniac/
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/romaniac.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'romaniac/converter'
|
2
|
+
|
3
|
+
def Roman(int)
|
4
|
+
Romaniac.new(int)
|
5
|
+
end
|
6
|
+
|
7
|
+
class Romaniac
|
8
|
+
# The VERSION file must be in the root directory of the library.
|
9
|
+
VERSION_FILE = File.expand_path('../../VERSION', __FILE__)
|
10
|
+
|
11
|
+
VERSION = File.exist?(VERSION_FILE) ?
|
12
|
+
File.read(VERSION_FILE) : '(could not find VERSION file)'
|
13
|
+
|
14
|
+
# The maximum possible Roman numeral.
|
15
|
+
LIMIT = 3999
|
16
|
+
|
17
|
+
ARABIC_PATTERN = /\A\d{1,4}\z/
|
18
|
+
|
19
|
+
DivisionError = Class.new(StandardError)
|
20
|
+
|
21
|
+
include Comparable
|
22
|
+
|
23
|
+
def initialize(int)
|
24
|
+
validate(int)
|
25
|
+
@int = int.to_i
|
26
|
+
@roman = Romaniac::Converter.to_roman(@int)
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
"(Roman: #@roman)"
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_i
|
34
|
+
@int
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
@roman
|
39
|
+
end
|
40
|
+
|
41
|
+
def <=>(other)
|
42
|
+
@int <=> other.to_i
|
43
|
+
end
|
44
|
+
|
45
|
+
def +(other)
|
46
|
+
self.class.new(@int + other.to_i)
|
47
|
+
end
|
48
|
+
|
49
|
+
def -(other)
|
50
|
+
self.class.new(@int - other.to_i)
|
51
|
+
end
|
52
|
+
|
53
|
+
def /(other)
|
54
|
+
int, fraction = @int.divmod(other.to_i)
|
55
|
+
if fraction.zero?
|
56
|
+
self.class.new(int)
|
57
|
+
else
|
58
|
+
raise Romaniac::DivisionError, "quotient isn't an integer"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def *(other)
|
63
|
+
self.class.new(@int * other.to_i)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def validate(int)
|
69
|
+
if int.is_a?(String)
|
70
|
+
valid_int = (int =~ ARABIC_PATTERN && (i = int.to_i) > 0 && i <= LIMIT)
|
71
|
+
if !valid_int
|
72
|
+
raise ArgumentError, %|invalid value for Roman(): "#{ int }"|
|
73
|
+
else
|
74
|
+
return
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if !int.is_a?(Fixnum)
|
79
|
+
raise TypeError, "can't convert #{ int.class } into Roman"
|
80
|
+
end
|
81
|
+
|
82
|
+
if int <= 0
|
83
|
+
raise RangeError, 'integer is too small to convert into Roman'
|
84
|
+
elsif int > LIMIT
|
85
|
+
raise RangeError, 'integer is too big to convert into Roman'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Romaniac::Const
|
2
|
+
|
3
|
+
ROMAN_PATTERN =
|
4
|
+
/\A(?i)M{0,3}(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])\z/i
|
5
|
+
|
6
|
+
# Handles the case when this file is required
|
7
|
+
# in the middle of a running program.
|
8
|
+
Romaniac::Converter::ARABIC_ROMAN.each_pair do |k, v|
|
9
|
+
Object.const_set(v, Roman(k))
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.define!(name)
|
13
|
+
if Romaniac::Converter::ARABIC_ROMAN.has_value?(name)
|
14
|
+
if RUBY_VERSION == '1.8.7'
|
15
|
+
arabic = Romaniac::Converter::ARABIC_ROMAN.index(name)
|
16
|
+
else
|
17
|
+
arabic = Romaniac::Converter::ARABIC_ROMAN.key(name)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
arabic = Romaniac::Converter.roman_to_arabic(name)
|
21
|
+
end
|
22
|
+
Object.const_set(name, Roman(arabic))
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class Object
|
28
|
+
def self.const_missing(name)
|
29
|
+
if (name = name.to_s) =~ Romaniac::Const::ROMAN_PATTERN
|
30
|
+
Romaniac::Const.define!(name)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
class Romaniac
|
2
|
+
module Converter
|
3
|
+
|
4
|
+
MAP = {
|
5
|
+
1 => 'I',
|
6
|
+
4 => 'IV',
|
7
|
+
5 => 'V',
|
8
|
+
9 => 'IX',
|
9
|
+
10 => 'X',
|
10
|
+
40 => 'XL',
|
11
|
+
50 => 'L',
|
12
|
+
90 => 'XC',
|
13
|
+
100 => 'C',
|
14
|
+
400 => 'CD',
|
15
|
+
500 => 'D',
|
16
|
+
900 => 'CM',
|
17
|
+
1000 => 'M'
|
18
|
+
}
|
19
|
+
|
20
|
+
INVERTED_MAP = [
|
21
|
+
['M' , 1000],
|
22
|
+
['CM', 900],
|
23
|
+
['D' , 500],
|
24
|
+
['CD', 400],
|
25
|
+
['C' , 100],
|
26
|
+
['XC', 90],
|
27
|
+
['L' , 50],
|
28
|
+
['XL', 40],
|
29
|
+
['X' , 10],
|
30
|
+
['IX', 9],
|
31
|
+
['V' , 5],
|
32
|
+
['IV', 4],
|
33
|
+
['I' , 1]
|
34
|
+
]
|
35
|
+
|
36
|
+
# Arabic numerals are used as key points that come in handy when the library
|
37
|
+
# dynamically creates new numerals.
|
38
|
+
KEY_POINTS = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
|
39
|
+
|
40
|
+
# Raw table of Arabic and Roman numerals. Fills out lazily.
|
41
|
+
ARABIC_ROMAN = Hash.new do |hash, int|
|
42
|
+
hash[int] = addends_of(int).map { |addend|
|
43
|
+
if hash.has_key?(addend)
|
44
|
+
hash[addend]
|
45
|
+
else
|
46
|
+
arabic_to_roman(addend)
|
47
|
+
end
|
48
|
+
}.join('')
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
# @api private
|
53
|
+
# @example
|
54
|
+
# addends_of(6969) #=> [6000, 900, 60, 9]
|
55
|
+
# @param [Integer] int
|
56
|
+
# @return [Array] addends of +int+ with base of 10
|
57
|
+
def addends_of(int)
|
58
|
+
addends = []
|
59
|
+
pad = 0
|
60
|
+
while int > 0
|
61
|
+
int, elem = int.divmod(10)
|
62
|
+
addends.unshift(10**pad * elem)
|
63
|
+
pad += 1
|
64
|
+
end
|
65
|
+
addends
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
# @example
|
70
|
+
# arabic_to_roman(142) #=> "CXLII"
|
71
|
+
# @param [Integer] int
|
72
|
+
# @return [String]
|
73
|
+
def arabic_to_roman(int)
|
74
|
+
roman = ''
|
75
|
+
while int > 0
|
76
|
+
point = KEY_POINTS.find { |key_point| key_point <= int }
|
77
|
+
times, int = int.divmod(point)
|
78
|
+
roman << MAP[point] * times
|
79
|
+
end
|
80
|
+
roman
|
81
|
+
end
|
82
|
+
|
83
|
+
# @api private
|
84
|
+
def to_roman(int)
|
85
|
+
ARABIC_ROMAN[int]
|
86
|
+
end
|
87
|
+
|
88
|
+
# @api private
|
89
|
+
# Also, stores the results of calculations into the ARABIC_ROMAN hash.
|
90
|
+
# @example
|
91
|
+
# arabic_to_roman("CXLII") #=> 142
|
92
|
+
# @param [String] roman
|
93
|
+
# @return [Integer]
|
94
|
+
def roman_to_arabic(roman)
|
95
|
+
arabic = 0
|
96
|
+
r = roman.dup
|
97
|
+
INVERTED_MAP.each do |k, v|
|
98
|
+
while r.index(k) == 0
|
99
|
+
arabic += v
|
100
|
+
r.slice!(k)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
ARABIC_ROMAN.merge!({ arabic => roman })
|
104
|
+
arabic
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/lib/romaniac/ext.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Enumerable
|
2
|
+
def with_roman_index(offset = 1)
|
3
|
+
return to_enum(:with_roman_index, offset) unless block_given?
|
4
|
+
each do |o|
|
5
|
+
val = yield(o, Roman(offset))
|
6
|
+
offset += 1
|
7
|
+
val
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def each_with_roman_index(&block)
|
12
|
+
with_roman_index(&block)
|
13
|
+
end
|
14
|
+
end
|
data/romaniac.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'romaniac'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
5
|
+
s.summary = 'The library for Roman numerals maniacs.'
|
6
|
+
s.description = 'The Romaniac library converts Arabic numerals to Roman numerals and vice versa.'
|
7
|
+
s.author = 'Kyrylo Silin'
|
8
|
+
s.email = 'kyrylosilin@gmail.com'
|
9
|
+
s.homepage = 'https://github.com/kyrylo/romaniac'
|
10
|
+
s.licenses = 'zlib'
|
11
|
+
|
12
|
+
s.require_path = 'lib'
|
13
|
+
s.files = `git ls-files`.split "\n"
|
14
|
+
|
15
|
+
s.add_development_dependency 'rake'
|
16
|
+
s.add_development_dependency 'minitest'
|
17
|
+
end
|
data/test/const_test.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class EnumerableTest < MiniTest::Unit::TestCase
|
4
|
+
def test_with_roman_index_method
|
5
|
+
assert_equal [[:a, Roman(1)], [:b, Roman(2)], [:c, Roman(3)]],
|
6
|
+
[:a, :b, :c].map.with_roman_index.to_a
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_with_roman_index_method_offset
|
10
|
+
assert_equal [[:a, Roman(10)], [:b, Roman(11)], [:c, Roman(12)]],
|
11
|
+
[:a, :b, :c].map.with_roman_index(10).to_a
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class FixnumTest < MiniTest::Unit::TestCase
|
4
|
+
def test_converting_a_number_to_a_roman_numeral
|
5
|
+
assert_equal Roman(124), 124.to_roman
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_conversion_of_too_big_numbers_raises_exception
|
9
|
+
e = assert_raises RangeError do
|
10
|
+
19214.to_roman
|
11
|
+
end
|
12
|
+
assert_match /integer is too big to convert into Roman/, e.message
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_conversion_of_zero_raises_exception
|
16
|
+
e = assert_raises RangeError do
|
17
|
+
0.to_roman
|
18
|
+
end
|
19
|
+
assert_match /integer is too small to convert into Roman/, e.message
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_conversion_of_negative_numbers_raises_exception
|
23
|
+
e = assert_raises RangeError do
|
24
|
+
0.to_roman
|
25
|
+
end
|
26
|
+
assert_match /integer is too small to convert into Roman/, e.message
|
27
|
+
end
|
28
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class RomaniacTest < MiniTest::Unit::TestCase
|
4
|
+
def test_arabic_to_roman_conversion
|
5
|
+
assert_equal '(Roman: I)', Roman(1).inspect
|
6
|
+
assert_equal '(Roman: CI)', Roman(101).inspect
|
7
|
+
assert_equal '(Roman: MMMCMXCIX)', Roman(3999).inspect
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_arabic_to_roman_conversion_from_string
|
11
|
+
assert_equal '(Roman: I)', Roman('1').inspect
|
12
|
+
assert_equal '(Roman: CI)', Roman('101').inspect
|
13
|
+
assert_equal '(Roman: MMMCMXCIX)', Roman('3999').inspect
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_malformed_string_argument_raises_exception
|
17
|
+
e = assert_raises ArgumentError do
|
18
|
+
Roman('...')
|
19
|
+
end
|
20
|
+
assert_match /invalid value for Roman\(\): "..."/, e.message
|
21
|
+
|
22
|
+
e = assert_raises ArgumentError do
|
23
|
+
Roman('aaa11')
|
24
|
+
end
|
25
|
+
assert_match /invalid value for Roman\(\): "aaa11"/, e.message
|
26
|
+
|
27
|
+
e = assert_raises ArgumentError do
|
28
|
+
Roman('11aaa')
|
29
|
+
end
|
30
|
+
assert_match /invalid value for Roman\(\): "11aaa"/, e.message
|
31
|
+
|
32
|
+
e = assert_raises ArgumentError do
|
33
|
+
Roman(' 11 ')
|
34
|
+
end
|
35
|
+
assert_match /invalid value for Roman\(\): " 11 "/, e.message
|
36
|
+
|
37
|
+
e = assert_raises ArgumentError do
|
38
|
+
Roman('4444')
|
39
|
+
end
|
40
|
+
assert_match /invalid value for Roman\(\): "4444"/, e.message
|
41
|
+
|
42
|
+
e = assert_raises ArgumentError do
|
43
|
+
Roman('4444sdad')
|
44
|
+
end
|
45
|
+
assert_match /invalid value for Roman\(\): "4444sdad"/, e.message
|
46
|
+
|
47
|
+
e = assert_raises ArgumentError do
|
48
|
+
Roman('0')
|
49
|
+
end
|
50
|
+
assert_match /invalid value for Roman\(\): "0"/, e.message
|
51
|
+
|
52
|
+
e = assert_raises ArgumentError do
|
53
|
+
Roman('-4444')
|
54
|
+
end
|
55
|
+
assert_match /invalid value for Roman\(\): "-4444"/, e.message
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_roman_to_arabic_conversion
|
59
|
+
assert_equal 201, Roman(201).to_i
|
60
|
+
assert_equal 3000, Roman(3000).to_i
|
61
|
+
assert_equal 66, Roman(66).to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_zero_to_roman_conversion_raises_exception
|
65
|
+
e = assert_raises RangeError do
|
66
|
+
Roman(0)
|
67
|
+
end
|
68
|
+
assert_match /integer is too small to convert into Roman/, e.message
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_negative_arabic_to_roman_conversion_raises_exception
|
72
|
+
e = assert_raises RangeError do
|
73
|
+
Roman(-1)
|
74
|
+
end
|
75
|
+
assert_match /integer is too small to convert into Roman/, e.message
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_noninteger_argument_value_raises_exception
|
79
|
+
e = assert_raises TypeError do
|
80
|
+
Roman(:'10')
|
81
|
+
end
|
82
|
+
assert_match /can't convert Symbol into Roman/, e.message
|
83
|
+
|
84
|
+
e = assert_raises TypeError do
|
85
|
+
Roman(10.55)
|
86
|
+
end
|
87
|
+
assert_match /can't convert Float into Roman/, e.message
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_too_big_integer_value_raises_exception
|
91
|
+
e = assert_raises RangeError do
|
92
|
+
Roman(4000)
|
93
|
+
end
|
94
|
+
assert_match /integer is too big to convert into Roman/, e.message
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_addition_works_correctly
|
98
|
+
assert_equal Roman(51), Roman(25) + Roman(26)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_too_big_sum_raises_exception
|
102
|
+
e = assert_raises RangeError do
|
103
|
+
Roman(2000) + Roman(3000)
|
104
|
+
end
|
105
|
+
assert_match /integer is too big to convert into Roman/, e.message
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_subtraction_works_correctly
|
109
|
+
assert_equal Roman(1), Roman(26) - Roman(25)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_too_small_difference_raises_exception
|
113
|
+
e = assert_raises RangeError do
|
114
|
+
Roman(26) - Roman(26)
|
115
|
+
end
|
116
|
+
assert_match /integer is too small to convert into Roman/, e.message
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_division_works_correctly
|
120
|
+
assert_equal Roman(5), Roman(20) / Roman(4)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_nonint_quotient_raises_exception
|
124
|
+
e = assert_raises Romaniac::DivisionError do
|
125
|
+
Roman(20) / Roman(3)
|
126
|
+
end
|
127
|
+
assert_match /quotient isn't an integer/, e.message
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_multiplication_works_correctly
|
131
|
+
assert_equal Roman(20), Roman(5) * Roman(4)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_too_big_product_raises_exception
|
135
|
+
e = assert_raises RangeError do
|
136
|
+
Roman(400) * Roman(300)
|
137
|
+
end
|
138
|
+
assert_match /integer is too big to convert into Roman/, e.message
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_comparison
|
142
|
+
assert Roman(20) == Roman(20)
|
143
|
+
assert Roman(20) > Roman(19)
|
144
|
+
assert Roman(20) < Roman(21)
|
145
|
+
assert Roman(20) != Roman(1)
|
146
|
+
assert Roman(20) >= Roman(20)
|
147
|
+
assert Roman(20) <= Roman(20)
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_to_s_returns_human_readable_representation
|
151
|
+
assert_equal 'C', Roman(100).to_s
|
152
|
+
assert_equal 'CCC', Roman(300).to_s
|
153
|
+
assert_equal 'XXI', Roman(21).to_s
|
154
|
+
end
|
155
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: romaniac
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kyrylo Silin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: minitest
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: The Romaniac library converts Arabic numerals to Roman numerals and vice
|
47
|
+
versa.
|
48
|
+
email: kyrylosilin@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- .travis.yml
|
55
|
+
- Gemfile
|
56
|
+
- LICENCE
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- VERSION
|
60
|
+
- lib/romaniac.rb
|
61
|
+
- lib/romaniac/const.rb
|
62
|
+
- lib/romaniac/converter.rb
|
63
|
+
- lib/romaniac/ext.rb
|
64
|
+
- lib/romaniac/ext/enumerable.rb
|
65
|
+
- lib/romaniac/ext/fixnum.rb
|
66
|
+
- romaniac.gemspec
|
67
|
+
- test/const_test.rb
|
68
|
+
- test/ext/enumerable_test.rb
|
69
|
+
- test/ext/fixnum_test.rb
|
70
|
+
- test/helper.rb
|
71
|
+
- test/romaniac_test.rb
|
72
|
+
homepage: https://github.com/kyrylo/romaniac
|
73
|
+
licenses:
|
74
|
+
- zlib
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.8.24
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: The library for Roman numerals maniacs.
|
97
|
+
test_files: []
|
98
|
+
has_rdoc:
|