roman_monkey 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE.md +20 -0
- data/README.md +89 -0
- data/lib/fast_roman.rb +20 -0
- data/lib/fast_roman_monkey.rb +18 -0
- data/lib/roman_monkey.rb +18 -0
- data/lib/roman_numeral.rb +69 -0
- data/lib/slow_roman.rb +49 -0
- data/roman_monkey.gemspec +30 -0
- data/spec/roman_monkey_spec.rb +50 -0
- data/spec/support/no_should_rspec.rb +9 -0
- data/spec/support/roman_test.rb +54 -0
- metadata +76 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Bardi Einarsson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
roman\_monkey
|
2
|
+
================
|
3
|
+
|
4
|
+
## Summary
|
5
|
+
|
6
|
+
simple roman numerals from 1 to 3999
|
7
|
+
|
8
|
+
## Description
|
9
|
+
|
10
|
+
roman\_monkey is a set of simple tools for formatting the numbers from 1 to 3999 as roman numerals, as well as, converting and validating the roman numerals themselves.
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Object instance methods
|
15
|
+
|
16
|
+
require 'roman_monkey'
|
17
|
+
# or require 'fast_roman_monkey'
|
18
|
+
# for pre calculated roman numerals
|
19
|
+
|
20
|
+
:i_to_roman
|
21
|
+
:roman_to_i
|
22
|
+
:roman? # is it a roman numeral?, :roman_to_i equivalent
|
23
|
+
|
24
|
+
irb prompt> require 'roman_monkey'
|
25
|
+
=> true
|
26
|
+
irb prompt> 1999.i_to_roman
|
27
|
+
=> "MCMXCIX"
|
28
|
+
irb prompt> '1999 was a good year'.i_to_roman
|
29
|
+
=> "MCMXCIX"
|
30
|
+
irb prompt> "MCMXCIX".roman_to_i
|
31
|
+
=> 1999
|
32
|
+
irb prompt> :MCMXCIX.roman_to_i
|
33
|
+
=> 1999
|
34
|
+
irb prompt> 'LD'.roman?
|
35
|
+
=> nil
|
36
|
+
irb prompt> 'CDL'.roman?
|
37
|
+
=> 450
|
38
|
+
irb prompt> 4000.i_to_roman
|
39
|
+
=> nil
|
40
|
+
irb prompt> 0.i_to_roman
|
41
|
+
=> nil
|
42
|
+
|
43
|
+
Simplest usage
|
44
|
+
|
45
|
+
require 'roman_numeral'
|
46
|
+
# for :i_to_roman module method
|
47
|
+
|
48
|
+
irb prompt> require 'roman_numeral'
|
49
|
+
=> true
|
50
|
+
irb prompt> RomanNumeral.i_to_roman 3888
|
51
|
+
=> "MMMDCCCLXXXVIII"
|
52
|
+
|
53
|
+
To add roman numeral validation
|
54
|
+
|
55
|
+
require 'slow_roman'
|
56
|
+
# for :roman_to_i module method
|
57
|
+
# or require 'fast_roman'
|
58
|
+
# for pre calculated roman numerals
|
59
|
+
|
60
|
+
irb prompt> require 'slow_roman'
|
61
|
+
=> true
|
62
|
+
irb prompt> RomanNumeral.i_to_roman 3888
|
63
|
+
=> "MMMDCCCLXXXVIII"
|
64
|
+
irb prompt> RomanNumeral.roman_to_i "MMMDCCCLXXXVIII"
|
65
|
+
=> 3888
|
66
|
+
|
67
|
+
## Requirements
|
68
|
+
|
69
|
+
Most likely any recent version of 1.9 ruby works.
|
70
|
+
|
71
|
+
## Test with rspec ~> 2.11, rspec -fd
|
72
|
+
|
73
|
+
Try the software in irb:
|
74
|
+
|
75
|
+
irb prompt> load 'spec/support/roman_test.rb'
|
76
|
+
|
77
|
+
Note, to find the gem installation directory:
|
78
|
+
|
79
|
+
irb prompt> require 'roman_monkey'
|
80
|
+
irb prompt> $".grep(/roman_monkey/)[0]
|
81
|
+
irb prompt> Object.new.method(:i_to_roman).source_location
|
82
|
+
irb prompt> exit
|
83
|
+
|
84
|
+
## License
|
85
|
+
|
86
|
+
Copyright (c) 2013 Bardi Einarsson. Released under the MIT License. See the [LICENSE][license] file for further details.
|
87
|
+
|
88
|
+
[license]: https://github.com/bardibardi/roman_monkey/blob/master/LICENSE.md
|
89
|
+
|
data/lib/fast_roman.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'roman_numeral'
|
2
|
+
|
3
|
+
module RomanNumeral
|
4
|
+
|
5
|
+
ROMANS = (1...4000).reduce([nil],&->(a,i){a<<slow_i_to_roman(i).to_sym})
|
6
|
+
INTS = ROMANS.each_with_index.reduce({},&->(h,p){h[p[0]]=p[1];h})
|
7
|
+
|
8
|
+
def self.i_to_roman i
|
9
|
+
sym = ROMANS[i.to_i]
|
10
|
+
return nil unless sym
|
11
|
+
sym.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.roman_to_i r
|
15
|
+
r = r.to_s.to_sym unless Symbol == r.class
|
16
|
+
INTS[r]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
data/lib/roman_monkey.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module RomanNumeral
|
2
|
+
|
3
|
+
I_TO_DIGIT = {
|
4
|
+
1 => :I,
|
5
|
+
2 => :II,
|
6
|
+
3 => :III,
|
7
|
+
4 => :IV,
|
8
|
+
5 => :V,
|
9
|
+
6 => :VI,
|
10
|
+
7 => :VII,
|
11
|
+
8 => :VIII,
|
12
|
+
9 => :IX,
|
13
|
+
10 => :X,
|
14
|
+
20 => :XX,
|
15
|
+
30 => :XXX,
|
16
|
+
40 => :XL,
|
17
|
+
50 => :L,
|
18
|
+
60 => :LX,
|
19
|
+
70 => :LXX,
|
20
|
+
80 => :LXXX,
|
21
|
+
90 => :XC,
|
22
|
+
100 => :C,
|
23
|
+
200 => :CC,
|
24
|
+
300 => :CCC,
|
25
|
+
400 => :CD,
|
26
|
+
500 => :D,
|
27
|
+
600 => :DC,
|
28
|
+
700 => :DCC,
|
29
|
+
800 => :DCCC,
|
30
|
+
900 => :CM,
|
31
|
+
1000 => :M,
|
32
|
+
2000 => :MM,
|
33
|
+
3000 => :MMM
|
34
|
+
}
|
35
|
+
|
36
|
+
def self.high_digit_value i
|
37
|
+
return nil unless -1 < i
|
38
|
+
return [0, 0] if 0 == i
|
39
|
+
shift = 0
|
40
|
+
v = i
|
41
|
+
while v > 9
|
42
|
+
v = v/10
|
43
|
+
shift += 1
|
44
|
+
end
|
45
|
+
while shift > 0
|
46
|
+
v *= 10
|
47
|
+
shift -= 1
|
48
|
+
end
|
49
|
+
[v, i - v]
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.i_to_roman i
|
53
|
+
r = []
|
54
|
+
rest = i.to_i
|
55
|
+
while (digit_value, rest = high_digit_value(rest); digit_value > 0)
|
56
|
+
roman_digit = I_TO_DIGIT[digit_value]
|
57
|
+
return nil unless roman_digit
|
58
|
+
r << roman_digit.to_s
|
59
|
+
end
|
60
|
+
return nil if 0 == r.length
|
61
|
+
r.join ''
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
alias :slow_i_to_roman :i_to_roman
|
66
|
+
end
|
67
|
+
|
68
|
+
end # RomanNumeral
|
69
|
+
|
data/lib/slow_roman.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'roman_numeral'
|
2
|
+
|
3
|
+
module RomanNumeral
|
4
|
+
|
5
|
+
DIGIT_TO_I = I_TO_DIGIT.invert
|
6
|
+
|
7
|
+
def self.next_roman_digit_of_size r, size
|
8
|
+
len = r.length
|
9
|
+
rn = r.slice(0, size)
|
10
|
+
v = DIGIT_TO_I[rn.to_sym]
|
11
|
+
return nil unless v
|
12
|
+
tail = r.slice(size, len - size)
|
13
|
+
tail = nil if '' == tail
|
14
|
+
[v, tail]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.next_roman_digit r
|
18
|
+
result = next_roman_digit_of_size r, 4
|
19
|
+
return result if result
|
20
|
+
result = next_roman_digit_of_size r, 3
|
21
|
+
return result if result
|
22
|
+
result = next_roman_digit_of_size r, 2
|
23
|
+
return result if result
|
24
|
+
next_roman_digit_of_size r, 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.roman_to_i r
|
28
|
+
return nil unless r
|
29
|
+
rest = r.to_s
|
30
|
+
return nil if 0 == rest.length
|
31
|
+
lastv = 10000
|
32
|
+
acc = 0
|
33
|
+
while rest
|
34
|
+
v, rest = next_roman_digit(rest)
|
35
|
+
return nil unless v
|
36
|
+
return nil unless lastv.to_s.length > v.to_s.length
|
37
|
+
acc += v
|
38
|
+
lastv = v
|
39
|
+
end
|
40
|
+
return nil if 0 == acc
|
41
|
+
acc
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
alias :slow_roman_to_i :roman_to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
end # RomanNumeral
|
49
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'roman_monkey'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2013-04-07'
|
5
|
+
s.summary = "simple roman numerals from 1 to 3999"
|
6
|
+
s.description = "roman_monkey is a set of simple tools for formatting the numbers from 1 to 3999 as roman numerals, as well as, converting and validating the roman numerals themselves."
|
7
|
+
|
8
|
+
s.authors = ['Bardi Einarsson']
|
9
|
+
s.email = ['bardi@hotmail.com']
|
10
|
+
s.homepage = 'https://github.com/bardibardi/roman_monkey'
|
11
|
+
s.required_ruby_version = '>= 1.9.2'
|
12
|
+
s.add_development_dependency('rspec', '~> 2.11')
|
13
|
+
|
14
|
+
s.files = %w(
|
15
|
+
.gitignore
|
16
|
+
Gemfile
|
17
|
+
LICENSE.md
|
18
|
+
README.md
|
19
|
+
roman_monkey.gemspec
|
20
|
+
lib/roman_numeral.rb
|
21
|
+
lib/slow_roman.rb
|
22
|
+
lib/fast_roman.rb
|
23
|
+
lib/roman_monkey.rb
|
24
|
+
lib/fast_roman_monkey.rb
|
25
|
+
spec/roman_monkey_spec.rb
|
26
|
+
spec/support/no_should_rspec.rb
|
27
|
+
spec/support/roman_test.rb
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'support/no_should_rspec'
|
2
|
+
require 'support/roman_test'
|
3
|
+
|
4
|
+
describe RomanNumeral do
|
5
|
+
|
6
|
+
it "should, for all roman numerals, convert integers to roman numerals and back" do
|
7
|
+
expect(RomanNumeral.reversible?).to be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should, for all roman numerals, slowly convert integers to roman numerals and back" do
|
11
|
+
expect(RomanNumeral.slow_reversible?).to be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Object do
|
17
|
+
|
18
|
+
it "should accept i_to_roman for number compatible types" do
|
19
|
+
expect(1.i_to_roman).to eq('I')
|
20
|
+
expect(1.9999.i_to_roman).to eq('I')
|
21
|
+
expect('1 potatoes'.i_to_roman).to eq('I')
|
22
|
+
expect(3999.i_to_roman).to eq('MMMCMXCIX')
|
23
|
+
expect('3999 marbles'.i_to_roman).to eq('MMMCMXCIX')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should accept roman_to_i for roman numeral compatible types" do
|
27
|
+
expect(:I.roman_to_i).to eq(1)
|
28
|
+
expect('I'.roman_to_i).to eq(1)
|
29
|
+
expect(:MMMCMXCIX.roman_to_i).to eq(3999)
|
30
|
+
expect('MMMCMXCIX'.roman_to_i).to eq(3999)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have i_to_roman return null for instances not in (1...4000)" do
|
34
|
+
expect(0.i_to_roman).to be_nil
|
35
|
+
expect('no potatoes'.i_to_roman).to be_nil
|
36
|
+
expect(4000.0.i_to_roman).to be_nil
|
37
|
+
expect(4000.i_to_roman).to be_nil
|
38
|
+
expect('4000 marbles'.i_to_roman).to be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have roman_to_i return null for instances not in (:I..:MMMCDXCIX)" do
|
42
|
+
expect(''.roman_to_i).to be_nil
|
43
|
+
expect(nil.roman_to_i).to be_nil
|
44
|
+
expect(:MMMM.roman_to_i).to be_nil
|
45
|
+
expect(:CCD.roman_to_i).to be_nil
|
46
|
+
expect(:LM.roman_to_i).to be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative '../../lib/roman_monkey'
|
2
|
+
require_relative '../../lib/fast_roman'
|
3
|
+
|
4
|
+
module RomanNumeral
|
5
|
+
|
6
|
+
def self.reversible?
|
7
|
+
(1...4000).each do |i|
|
8
|
+
s = i_to_roman i
|
9
|
+
return nil unless s
|
10
|
+
i2 = roman_to_i s
|
11
|
+
return nil unless i2
|
12
|
+
return nil unless i == i2
|
13
|
+
end
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.slow_reversible?
|
18
|
+
(1...4000).each do |i|
|
19
|
+
s = slow_i_to_roman i
|
20
|
+
return nil unless s
|
21
|
+
i2 = slow_roman_to_i s
|
22
|
+
return nil unless i2
|
23
|
+
return nil unless i == i2
|
24
|
+
end
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.reversible2?
|
29
|
+
(1...4000).each do |i|
|
30
|
+
s = i_to_roman i
|
31
|
+
unless s
|
32
|
+
p 'i'
|
33
|
+
p i
|
34
|
+
return nil unless s
|
35
|
+
end
|
36
|
+
i2 = roman_to_i s
|
37
|
+
unless i2
|
38
|
+
p 's'
|
39
|
+
p s
|
40
|
+
return nil unless i2
|
41
|
+
end
|
42
|
+
unless i == i2
|
43
|
+
p 'i'
|
44
|
+
p i
|
45
|
+
p 'i2'
|
46
|
+
p i2
|
47
|
+
return nil unless i == i2
|
48
|
+
end
|
49
|
+
end
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
end # RomanNumeral
|
54
|
+
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roman_monkey
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Bardi Einarsson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.11'
|
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: '2.11'
|
30
|
+
description: roman_monkey is a set of simple tools for formatting the numbers from
|
31
|
+
1 to 3999 as roman numerals, as well as, converting and validating the roman numerals
|
32
|
+
themselves.
|
33
|
+
email:
|
34
|
+
- bardi@hotmail.com
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- .gitignore
|
40
|
+
- Gemfile
|
41
|
+
- LICENSE.md
|
42
|
+
- README.md
|
43
|
+
- roman_monkey.gemspec
|
44
|
+
- lib/roman_numeral.rb
|
45
|
+
- lib/slow_roman.rb
|
46
|
+
- lib/fast_roman.rb
|
47
|
+
- lib/roman_monkey.rb
|
48
|
+
- lib/fast_roman_monkey.rb
|
49
|
+
- spec/roman_monkey_spec.rb
|
50
|
+
- spec/support/no_should_rspec.rb
|
51
|
+
- spec/support/roman_test.rb
|
52
|
+
homepage: https://github.com/bardibardi/roman_monkey
|
53
|
+
licenses: []
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.9.2
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.8.25
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: simple roman numerals from 1 to 3999
|
76
|
+
test_files: []
|