romans 0.1.0

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kristian Mandrup
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.
@@ -0,0 +1,19 @@
1
+ # Romans
2
+
3
+ Roman literals
4
+
5
+ ## Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ ## License
16
+
17
+ Author: +Dave Burt <dave at burt.id.au>+
18
+
19
+ +Fine print: Provided as is. Use at your own risk. Credit's appreciated if you use my code.+
@@ -0,0 +1,42 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "romans"
5
+ gem.summary = %Q{Roman numerals}
6
+ gem.description = %Q{Roman numerals library}
7
+ gem.email = "kmandrup@gmail.com"
8
+ gem.homepage = "http://github.com/kristianmandrup/romans"
9
+ gem.authors = ["Kristian Mandrup"]
10
+ gem.add_development_dependency "rspec", ">= 1.2.9"
11
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
12
+ end
13
+ Jeweler::GemcutterTasks.new
14
+ rescue LoadError
15
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
16
+ end
17
+
18
+ # require 'spec/rake/spectask'
19
+ # Spec::Rake::SpecTask.new(:spec) do |spec|
20
+ # spec.libs << 'lib' << 'spec'
21
+ # spec.spec_files = FileList['spec/**/*_spec.rb']
22
+ # end
23
+ #
24
+ # Spec::Rake::SpecTask.new(:rcov) do |spec|
25
+ # spec.libs << 'lib' << 'spec'
26
+ # spec.pattern = 'spec/**/*_spec.rb'
27
+ # spec.rcov = true
28
+ # end
29
+ #
30
+ # task :spec => :check_dependencies
31
+ #
32
+ # task :default => :spec
33
+ #
34
+ # require 'rake/rdoctask'
35
+ # Rake::RDocTask.new do |rdoc|
36
+ # version = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+ #
38
+ # rdoc.rdoc_dir = 'rdoc'
39
+ # rdoc.title = "romans #{version}"
40
+ # rdoc.rdoc_files.include('README*')
41
+ # rdoc.rdoc_files.include('lib/**/*.rb')
42
+ # end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,184 @@
1
+ #
2
+ # Roman numerals
3
+ #
4
+ # Generates roman numerals from integers and vice-versa
5
+ #
6
+ # Author: Dave Burt <dave at burt.id.au>
7
+ #
8
+ # Fine print: Provided as is. Use at your own risk. Credit's appreciated if you use my code.
9
+ #
10
+
11
+
12
+ # http://media.pragprog.com/titles/fr_quiz/code/roman_numerals/roman_numerals.rb
13
+
14
+ # Contains methods to convert integers to Roman numeral strings, and vice versa.
15
+ module RomanNumerals
16
+
17
+ # Maps Roman numeral digits to their integer values
18
+ DIGITS = {
19
+ 'I' => 1,
20
+ 'V' => 5,
21
+ 'X' => 10,
22
+ 'L' => 50,
23
+ 'C' => 100,
24
+ 'D' => 500,
25
+ 'M' => 1000
26
+ }
27
+
28
+ # The largest integer representable as a Roman numerable by this module
29
+ MAX = 3999
30
+
31
+ # Maps some integers to their Roman numeral values
32
+ @@digits_lookup = DIGITS.inject({
33
+ 4 => 'IV',
34
+ 9 => 'IX',
35
+ 40 => 'XL',
36
+ 90 => 'XC',
37
+ 400 => 'CD',
38
+ 900 => 'CM'}) do |memo, pair|
39
+ memo.update({pair.last => pair.first})
40
+ end
41
+
42
+ # Based on Regular Expression Grabbag in the O'Reilly Perl Cookbook, #6.23
43
+ REGEXP = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i
44
+
45
+ # Converts +int+ to a Roman numeral
46
+ def self.from_integer(int)
47
+ return nil if int < 0 || int > MAX
48
+ remainder = int
49
+ result = ''
50
+ @@digits_lookup.keys.sort.reverse.each do |digit_value|
51
+ while remainder >= digit_value
52
+ remainder -= digit_value
53
+ result += @@digits_lookup[digit_value]
54
+ end
55
+ break if remainder <= 0
56
+ end
57
+ result
58
+ end
59
+
60
+ # Converts +roman_string+, a Roman numeral, to an integer
61
+ def self.to_integer(roman_string)
62
+ return nil unless roman_string.is_roman_numeral?
63
+ last = nil
64
+ roman_string.to_s.upcase.split(//).reverse.inject(0) do |memo, digit|
65
+ if digit_value = DIGITS[digit]
66
+ if last && last > digit_value
67
+ memo -= digit_value
68
+ else
69
+ memo += digit_value
70
+ end
71
+ last = digit_value
72
+ end
73
+ memo
74
+ end
75
+ end
76
+
77
+ # Returns true if +string+ is a Roman numeral.
78
+ def self.is_roman_numeral?(string)
79
+ REGEXP =~ string
80
+ end
81
+ end
82
+
83
+
84
+
85
+ class String
86
+ # Considers string a Roman numeral,
87
+ # and converts it to the corresponding integer.
88
+ def to_i_roman
89
+ RomanNumerals.to_integer(self)
90
+ end
91
+ # Returns true if the subject is a Roman numeral.
92
+ def is_roman_numeral?
93
+ RomanNumerals.is_roman_numeral?(self)
94
+ end
95
+ end
96
+ class Integer
97
+ # Converts this integer to a Roman numeral.
98
+ def to_s_roman
99
+ RomanNumerals.from_integer(self) || ''
100
+ end
101
+ end
102
+
103
+
104
+
105
+ # Integers that look like Roman numerals
106
+ class RomanNumeral
107
+ attr_reader :to_s, :to_i
108
+
109
+ @@all_roman_numerals = []
110
+
111
+ # May be initialized with either a string or an integer
112
+ def initialize(value)
113
+ case value
114
+ when Integer
115
+ @to_s = value.to_s_roman
116
+ @to_i = value
117
+ else
118
+ @to_s = value.to_s
119
+ @to_i = value.to_s.to_i_roman
120
+ end
121
+ @@all_roman_numerals[to_i] = self
122
+ end
123
+
124
+ # Factory method: returns an equivalent existing object if such exists,
125
+ # or a new one
126
+ def self.get(value)
127
+ if value.is_a?(Integer)
128
+ to_i = value
129
+ else
130
+ to_i = value.to_s.to_i_roman
131
+ end
132
+ @@all_roman_numerals[to_i] || RomanNumeral.new(to_i)
133
+ end
134
+
135
+ def inspect
136
+ to_s
137
+ end
138
+
139
+ # Delegates missing methods to Integer, converting arguments to Integer,
140
+ # and converting results back to RomanNumeral
141
+ def method_missing(sym, *args)
142
+ unless to_i.respond_to?(sym)
143
+ raise NoMethodError.new(
144
+ "undefined method '#{sym}' for #{self}:#{self.class}")
145
+ end
146
+ result = to_i.send(sym,
147
+ *args.map {|arg| arg.is_a?(RomanNumeral) ? arg.to_i : arg })
148
+ case result
149
+ when Integer
150
+ RomanNumeral.get(result)
151
+ when Enumerable
152
+ result.map do |element|
153
+ element.is_a?(Integer) ? RomanNumeral.get(element) : element
154
+ end
155
+ else
156
+ result
157
+ end
158
+ end
159
+ end
160
+
161
+
162
+
163
+ # Enables uppercase Roman numerals to be used interchangeably with integers.
164
+ # They are autovivified RomanNumeral constants
165
+ # Synopsis:
166
+ # 4 + IV #=> VIII
167
+ # VIII + 7 #=> XV
168
+ # III ** III #=> XXVII
169
+ # VIII.divmod(III) #=> [II, II]
170
+ # def Object.const_missing sym
171
+ # unless RomanNumerals::REGEXP === sym.to_s
172
+ # raise NameError.new("uninitialized constant: #{sym}")
173
+ # end
174
+ # const_set(sym, RomanNumeral.get(sym))
175
+ # end
176
+
177
+
178
+ def Object.const_missing sym
179
+ if RomanNumerals::REGEXP === sym.to_s
180
+ const_set(sym, RomanNumeral.get(sym))
181
+ return
182
+ end
183
+ super
184
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Roman numerals" do
4
+ it "should add roman numerals correctly" do
5
+ IV = RomanNumeral.get(4)
6
+ res = IV + 5
7
+ res.to_s.should == 'IX'
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'rspec/autorun'
3
+ require 'romans'
4
+
5
+ # RSpec.configure do |config|
6
+ # end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: romans
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Kristian Mandrup
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-25 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 2
31
+ - 9
32
+ version: 1.2.9
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: Roman numerals library
36
+ email: kmandrup@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - lib/romans.rb
52
+ - spec/romans_spec.rb
53
+ - spec/spec.opts
54
+ - spec/spec_helper.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/kristianmandrup/romans
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.7
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Roman numerals
87
+ test_files:
88
+ - spec/romans_spec.rb
89
+ - spec/spec_helper.rb