cousin_roman 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -2
- data/lib/cousin_roman/arabian.rb +5 -23
- data/lib/cousin_roman/roman.rb +12 -6
- data/lib/cousin_roman/version.rb +1 -1
- data/lib/cousin_roman.rb +12 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec3fa2cc7d9e4ab2b07e528b54976fb4133a8b92
|
4
|
+
data.tar.gz: 9bdac0d47492a5a17cc9eee724a856364987e67c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bebb3279b63fdca8189a5c1290a7ebb4baeb76abf42e88081e19614dc8bd7d386d8c70aefc7c416e91386566be700f96b0e17144d83469e8e4e043b64b6aa89
|
7
|
+
data.tar.gz: f6834054b705eb3e16f7aeb9b93f01c90b2622cf7dc88524570a4fa02d4ccb779a49bcb0bdb028fcdcaea8d220d9b43a1de3eac088958f7a9d757ba815b6ea12
|
data/README.md
CHANGED
@@ -1,9 +1,23 @@
|
|
1
1
|
# CousinRoman
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
CousinRoman provides functionality to convert between Roman and Arabian numerals.
|
5
4
|
The functionality provided via String and Integer extensions.
|
6
5
|
|
6
|
+
## Roman numbers and conversion rules
|
7
|
+
|
8
|
+
CousinRoman follows strict roman notation with subtractive rule, i.e.
|
9
|
+
|
10
|
+
1. Letters should be ordered by decreasing of magnitude.
|
11
|
+
2. Only I, X, C, M can be repeated, but up to three times.
|
12
|
+
3. Letter with lower magnitude can appear BEFORE letter with higher magnitude,
|
13
|
+
but only in the following cases: IV, IX, XL, XC, CD, CM - lets call them **subtractives**
|
14
|
+
4. **subtractives** and regular letters cannot appear within the same power,
|
15
|
+
i.e. `ivi` is not allowed.
|
16
|
+
|
17
|
+
Therefore, only numbers within range of 1..3999 can be represented in roman notation.
|
18
|
+
|
19
|
+
CousinRoman is thoroughly spec'ed, and considered reliable in following these rules.
|
20
|
+
|
7
21
|
## Installation
|
8
22
|
|
9
23
|
Add this line to your application's Gemfile:
|
@@ -38,6 +52,10 @@ For example:
|
|
38
52
|
'100500'.to_roman! # => TypeError: not a valid roman number
|
39
53
|
```
|
40
54
|
|
55
|
+
`String#to_arabian(!)` is case insensitive.
|
56
|
+
|
57
|
+
`Integer#to_roman(!)` returns numerals in upper case.
|
58
|
+
|
41
59
|
## Testing
|
42
60
|
|
43
61
|
Just run
|
data/lib/cousin_roman/arabian.rb
CHANGED
@@ -28,14 +28,14 @@ module CousinRoman
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def build_roman(thousands, hundreds, tens, ones)
|
31
|
-
build_pow(thousands,
|
32
|
-
build_pow(hundreds,
|
33
|
-
build_pow(tens,
|
34
|
-
build_pow(ones,
|
31
|
+
build_pow(thousands, 3) +
|
32
|
+
build_pow(hundreds, 2) +
|
33
|
+
build_pow(tens, 1) +
|
34
|
+
build_pow(ones, 0)
|
35
35
|
end
|
36
36
|
|
37
37
|
def build_pow(number, pow)
|
38
|
-
literals =
|
38
|
+
literals = CousinRoman.literals_for_pow pow
|
39
39
|
|
40
40
|
case number
|
41
41
|
when 1..3 then literals[:one]*number
|
@@ -45,23 +45,5 @@ module CousinRoman
|
|
45
45
|
else ""
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
49
|
-
def pow_literals(pow)
|
50
|
-
one_literal, _ = ONES.find do |literal, value|
|
51
|
-
value >= 10 ** (pow - 1) and value < 10 ** pow
|
52
|
-
end
|
53
|
-
five_literal, _ = FIVES.find do |literal, value|
|
54
|
-
value >= 10 ** (pow - 1) and value < 10 ** pow
|
55
|
-
end
|
56
|
-
subtractive_literals = {}
|
57
|
-
SUBTRACTIVES.select do |literal, value|
|
58
|
-
value >= 10 ** (pow - 1) and value < 10 ** pow
|
59
|
-
end.each do |literal, number|
|
60
|
-
order = number / (10 ** (pow - 1))
|
61
|
-
subtractive_literals[order] = literal
|
62
|
-
end
|
63
|
-
|
64
|
-
{one: one_literal, five: five_literal, subtractives: subtractive_literals}
|
65
|
-
end
|
66
48
|
end
|
67
49
|
end
|
data/lib/cousin_roman/roman.rb
CHANGED
@@ -18,12 +18,11 @@ module CousinRoman
|
|
18
18
|
# 2. Sum this numeric values to get the final answer
|
19
19
|
def convert(number)
|
20
20
|
intermediate = number.dup.downcase
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
21
|
+
compound = braketize_value_of SUBTRACTIVES
|
22
|
+
singular = braketize_value_of ONES.merge(FIVES)
|
23
|
+
|
24
|
+
compound.each { |literal, val| intermediate.gsub!(literal, val) }
|
25
|
+
singular.each { |literal, val| intermediate.gsub!(literal, val) }
|
27
26
|
|
28
27
|
intermediate.scan(/\((\d*)\)/).reduce(0) do |sum, term|
|
29
28
|
sum + term.first.to_i
|
@@ -47,5 +46,12 @@ module CousinRoman
|
|
47
46
|
def roman_regex
|
48
47
|
/^(M{0,3})(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i
|
49
48
|
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Make hash of the following structure {'i' => '(1)', 'v' => '(5)'...}
|
53
|
+
def braketize_value_of(factors)
|
54
|
+
Hash[factors.map { |literal, val| [literal, "(#{val})"] } ]
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
data/lib/cousin_roman/version.rb
CHANGED
data/lib/cousin_roman.rb
CHANGED
@@ -38,4 +38,16 @@ module CousinRoman
|
|
38
38
|
}
|
39
39
|
|
40
40
|
FACTORS = ONES.merge(FIVES).merge(SUBTRACTIVES)
|
41
|
+
|
42
|
+
def self.literals_for_pow(pow)
|
43
|
+
one, five = ONES.keys[pow], FIVES.keys[pow]
|
44
|
+
subtractives = if pow.between? 0, 2
|
45
|
+
skeys = SUBTRACTIVES.keys
|
46
|
+
{ 4 => skeys[pow*2], 9 => skeys[pow*2 + 1] }
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
{ one: one, five: five, subtractives: subtractives }
|
52
|
+
end
|
41
53
|
end
|