romaniac 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.
- 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:
|