facets 2.8.2 → 2.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +13 -11
- data/HISTORY.rdoc +58 -0
- data/lib/core/facets/array/recursive.rb +91 -0
- data/lib/core/facets/array/recursively.rb +2 -2
- data/lib/core/facets/array/traverse.rb +23 -6
- data/lib/core/facets/enumerable/collisions.rb +1 -0
- data/lib/core/facets/enumerable/commonality.rb +4 -2
- data/lib/core/facets/enumerable/graph.rb +37 -1
- data/lib/core/facets/enumerable/mash.rb +1 -39
- data/lib/core/facets/enumerable/recursive.rb +75 -0
- data/lib/core/facets/enumerable/visit.rb +30 -0
- data/lib/core/facets/file/ext.rb +36 -0
- data/lib/core/facets/hash/graph.rb +18 -0
- data/lib/core/facets/hash/mash.rb +1 -18
- data/lib/core/facets/hash/recursive.rb +180 -0
- data/lib/core/facets/hash/recursive_merge.rb +6 -0
- data/lib/core/facets/hash/recursively.rb +2 -2
- data/lib/core/facets/hash/to_module.rb +26 -0
- data/lib/core/facets/hash/to_proc.rb +2 -2
- data/lib/core/facets/hash/traverse.rb +19 -13
- data/lib/core/facets/kernel/assign.rb +63 -0
- data/lib/core/facets/kernel/assign_from.rb +45 -0
- data/lib/core/facets/kernel/dup.rb +63 -0
- data/lib/core/facets/kernel/instance.rb +156 -0
- data/lib/core/facets/kernel/instance_assign.rb +1 -22
- data/lib/core/facets/kernel/meta_def.rb +4 -0
- data/lib/core/facets/kernel/populate.rb +1 -74
- data/lib/core/facets/kernel/set_from.rb +2 -0
- data/lib/core/facets/kernel/try_dup.rb +1 -0
- data/lib/core/facets/module/set.rb +36 -0
- data/lib/core/facets/objectspace/reflect.rb +45 -0
- data/lib/core/facets/struct/attributes.rb +6 -2
- data/lib/core/facets/symbol/op_div.rb +19 -0
- data/lib/core/facets/to_hash.rb +12 -0
- data/lib/more/facets/casting_hash.rb +172 -0
- data/lib/more/facets/pathname.rb +36 -0
- data/lib/more/facets/prepend.rb +57 -0
- data/lib/more/facets/random.rb +19 -3
- data/lib/more/facets/roman.rb +46 -153
- data/lib/more/facets/stash.rb +148 -33
- data/meta/released +1 -1
- data/meta/version +1 -1
- data/test/core/array/test_recursive.rb +18 -0
- data/test/core/enumerable/test_recursive.rb +18 -0
- data/test/core/file/test_ext.rb +31 -0
- data/test/core/hash/test_recursive.rb +23 -0
- data/test/core/hash/test_to_module.rb +21 -0
- data/test/core/kernel/test_assign.rb +57 -0
- data/test/core/kernel/test_assign_from.rb +20 -0
- data/test/more/test_prepend.rb +28 -0
- data/test/more/test_random.rb +40 -4
- metadata +39 -10
- data/lib/core/facets/kernel/instance_variables.rb +0 -97
- data/lib/more/facets/instance_eval.rb +0 -50
- data/lib/more/facets/ioredirect.rb +0 -77
- data/lib/more/facets/plugin_manager.rb +0 -50
- data/test/core/kernel/test_populate.rb +0 -46
@@ -1,11 +1,15 @@
|
|
1
1
|
class Struct
|
2
2
|
|
3
|
-
# Returns a hash containing the names and values
|
3
|
+
# Returns a hash containing the names and values
|
4
|
+
# for all instance settings in the Struct.
|
5
|
+
#
|
6
|
+
# This will eventually be deprecated in favor of #to_h.
|
7
|
+
|
4
8
|
def attributes
|
5
9
|
h = {}
|
6
10
|
each_pair { |k,v| h[k] = v }
|
7
11
|
h
|
8
12
|
end
|
9
13
|
|
10
|
-
end
|
14
|
+
end
|
11
15
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Symbol
|
2
|
+
|
3
|
+
# Join with _path_ as a file path.
|
4
|
+
#
|
5
|
+
# :merb / "core_ext" #=> "merb/core_ext"
|
6
|
+
# :merb / :core_ext / :string #=> "merb/core_ext/string"
|
7
|
+
#
|
8
|
+
# @param [#to_s] path The path component(s) to append.
|
9
|
+
#
|
10
|
+
# @return [String] The receiver (as path string), concatenated with _path_.
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
|
14
|
+
def /(path)
|
15
|
+
File.join(to_s, path.to_s)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
data/lib/core/facets/to_hash.rb
CHANGED
@@ -0,0 +1,172 @@
|
|
1
|
+
# CastingHash is just like Hash, except that all keys and values
|
2
|
+
# are passed through casting procedures.
|
3
|
+
#--
|
4
|
+
# TODO: Handle default_proc.
|
5
|
+
#++
|
6
|
+
class CastingHash < Hash
|
7
|
+
|
8
|
+
# Default key conversion procedure.
|
9
|
+
KEY_PROC = lambda{ |x| x } #.to_s }
|
10
|
+
|
11
|
+
# Default value conversion procedure.
|
12
|
+
VAL_PROC = lambda{ |x| x }
|
13
|
+
|
14
|
+
#
|
15
|
+
def self.[](hash)
|
16
|
+
s = new
|
17
|
+
hash.each{ |k,v| s[k] = v }
|
18
|
+
s
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
def initialize(hash, value_cast=nil, &key_cast)
|
23
|
+
@key_proc = key_cast || KEY_PROC
|
24
|
+
@value_proc = value_cast.to_proc || VAL_PROC
|
25
|
+
hash.each{ |k,v| self[k] = v }
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
def key_proc
|
30
|
+
@key_proc
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
def key_proc=(proc)
|
35
|
+
@key_proc = proc.to_proc
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
def value_proc
|
40
|
+
@value_proc
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
def value_proc=(proc)
|
45
|
+
@value_proc = proc.to_proc
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
def [](k)
|
50
|
+
super(key_proc[k])
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
def []=(k,v)
|
55
|
+
super(key_proc[k], value_proc[v])
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
def <<(other)
|
60
|
+
case other
|
61
|
+
when Hash
|
62
|
+
super(cast(other))
|
63
|
+
when Array
|
64
|
+
self[other[0]] = other[1]
|
65
|
+
else
|
66
|
+
raise ArgumentError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fetch(k)
|
71
|
+
super(key_proc[k])
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
def store(k, v)
|
76
|
+
super(key_proc[k], value_proc[v])
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
def key?(k)
|
81
|
+
super(key_proc[k])
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
def has_key?(k)
|
86
|
+
super(key_proc[k])
|
87
|
+
end
|
88
|
+
|
89
|
+
# Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
|
90
|
+
#
|
91
|
+
# foo = { :name=>'Gavin', :wife=>:Lisa }.to_stash
|
92
|
+
# foo.rekey!{ |k| k.upcase } #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
|
93
|
+
# foo.inspect #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
|
94
|
+
#
|
95
|
+
def rekey!(*args, &block)
|
96
|
+
# for backward comptability (DEPRECATE?).
|
97
|
+
block = args.pop.to_sym.to_proc if args.size == 1
|
98
|
+
if args.empty?
|
99
|
+
block = lambda{|k| k} unless block
|
100
|
+
keys.each do |k|
|
101
|
+
nk = block[k]
|
102
|
+
self[nk] = delete(k) #if nk
|
103
|
+
end
|
104
|
+
else
|
105
|
+
raise ArgumentError, "3 for 2" if block
|
106
|
+
to, from = *args
|
107
|
+
self[to] = delete(from) if has_key?(from)
|
108
|
+
end
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
def rekey(*args, &block)
|
114
|
+
dup.rekey!(*args, &block)
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
def delete(k)
|
119
|
+
super(key_proc[k])
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
def update(other)
|
124
|
+
super(cast(other))
|
125
|
+
end
|
126
|
+
|
127
|
+
# Same as #update.
|
128
|
+
def merge!(other)
|
129
|
+
super(cast(other))
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
def replace(other)
|
134
|
+
super(cast(other))
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
def values_at(*keys)
|
139
|
+
super(keys.map(&key_proc))
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
def to_hash
|
144
|
+
h = {}; each{ |k,v| h[k] = v }; h
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
alias_method :to_h, :to_hash
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
#
|
153
|
+
def cast(hash)
|
154
|
+
h
|
155
|
+
hash.each do |k,v|
|
156
|
+
h[key_proc[k]] = value_proc[v]
|
157
|
+
end
|
158
|
+
h
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
class Hash
|
165
|
+
|
166
|
+
# Convert a Hash to a Stash object.
|
167
|
+
def to_casting_hash(value_cast=nil, &key_cast)
|
168
|
+
CastingHash.new(self, value_cast, &key_cast)
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
data/lib/more/facets/pathname.rb
CHANGED
@@ -25,6 +25,10 @@ require 'facets/file/rootname'
|
|
25
25
|
|
26
26
|
class Pathname
|
27
27
|
|
28
|
+
# Alias #to_s to #to_str when #to_str is not defined.
|
29
|
+
#
|
30
|
+
alias_method(:to_str, :to_s) unless method_defined?(:to_str)
|
31
|
+
|
28
32
|
# Alternate to Pathname#new.
|
29
33
|
#
|
30
34
|
# Pathname['/usr/share']
|
@@ -148,6 +152,38 @@ class Pathname
|
|
148
152
|
::FileUtils.outofdate?(to_s, sources.flatten)
|
149
153
|
end
|
150
154
|
|
155
|
+
# Recursively visit a directory located by its path, yielding each resource
|
156
|
+
# as its full matching pathname object. If called on a file, yield the file.
|
157
|
+
#
|
158
|
+
# call-seq:
|
159
|
+
# visit => yield each file
|
160
|
+
# visit(all: true) => yield visited directories as well
|
161
|
+
# visit(hidden: true) => yield hidden files and directories as well
|
162
|
+
#
|
163
|
+
# Example use case:
|
164
|
+
#
|
165
|
+
# # get rid of any file but *.haml within app/**/*
|
166
|
+
# Pathname.new("app").visit do |f|
|
167
|
+
# FileUtils.rm_f(f) unless f.to_s =~ /\.haml$/
|
168
|
+
# puts "!!! deleting #{f}"
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# CREDIT: Jean-Denis Vauguet
|
172
|
+
def visit(options = {:all => false, :hidden => false})
|
173
|
+
if self.directory?
|
174
|
+
children.each do |entry|
|
175
|
+
next if entry.basename.to_s[0] == "." && !options[:hidden]
|
176
|
+
yield(entry) unless entry.directory? && !options[:all]
|
177
|
+
#entry.visit(:all => options[:all]) { |sub_entry| yield sub_entry } if entry.directory?
|
178
|
+
entry.visit(:all => options[:all], :hidden => options[:hidden]) do |sub_entry|
|
179
|
+
yield(sub_entry)
|
180
|
+
end if entry.directory?
|
181
|
+
end
|
182
|
+
else
|
183
|
+
yield self
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
151
187
|
# # Already included in 1.8.4+ version of Ruby (except for inclusion flag)
|
152
188
|
# if not instance_methods.include?(:ascend)
|
153
189
|
#
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# :title: Prepend
|
2
|
+
# :copyright: Copyright (c) 2005 Thomas Sawyer
|
3
|
+
# :license: Ruby License
|
4
|
+
# :description: Prepend a module to another module, or to a class.
|
5
|
+
|
6
|
+
# = Prepend
|
7
|
+
#
|
8
|
+
# This is a module prepend system, which provides an elegant
|
9
|
+
# way to prepend code to the class hierarchy rather then append
|
10
|
+
# it (a la #include).
|
11
|
+
#
|
12
|
+
# class C
|
13
|
+
# def f
|
14
|
+
# "f"
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# module M
|
19
|
+
# def f
|
20
|
+
# '{' + super + '}'
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# class C
|
25
|
+
# prepend M
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# c = C.new
|
29
|
+
# c.f #=> "{f}"
|
30
|
+
#
|
31
|
+
# This works by overriding Class#new so that all prepended modules
|
32
|
+
# extend new instances of the class upon instantiation.
|
33
|
+
#
|
34
|
+
# If needed the original #new method has been aliased as #init.
|
35
|
+
|
36
|
+
class Class
|
37
|
+
|
38
|
+
#
|
39
|
+
def prepend(*mods)
|
40
|
+
@prepend ||= []
|
41
|
+
@prepend.concat(mods)
|
42
|
+
@prepend
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :init, :new
|
46
|
+
|
47
|
+
def new(*args, &blk)
|
48
|
+
o = allocate
|
49
|
+
prepend.each do |mod|
|
50
|
+
o.extend(mod)
|
51
|
+
end
|
52
|
+
o.__send__(:initialize, *args, &blk) #if private_method_defined?(:initialize)
|
53
|
+
o
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
data/lib/more/facets/random.rb
CHANGED
@@ -53,7 +53,7 @@ require 'facets/string/shatter'
|
|
53
53
|
module Random
|
54
54
|
|
55
55
|
class << self
|
56
|
-
#
|
56
|
+
# Alias for Kernel#rand.
|
57
57
|
alias_method :number, :rand
|
58
58
|
public :number
|
59
59
|
end
|
@@ -79,6 +79,8 @@ module Random
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
#
|
83
|
+
|
82
84
|
module Object
|
83
85
|
|
84
86
|
# Random generator that returns true or false.
|
@@ -106,9 +108,23 @@ module Random
|
|
106
108
|
# (1..4).at_rand #=> 2
|
107
109
|
# (1..4).at_rand #=> 4
|
108
110
|
#
|
111
|
+
# (1.5..2.5).at_rand #=> 2.06309842754533
|
112
|
+
# (1.5..2.5).at_rand #=> 1.74976944931541
|
113
|
+
#
|
114
|
+
# ('a'..'z').at_rand #=> 'q'
|
115
|
+
# ('a'..'z').at_rand #=> 'f'
|
116
|
+
#
|
117
|
+
# CREDIT: Lavir the Whiolet
|
118
|
+
|
109
119
|
def at_rand
|
110
|
-
|
111
|
-
|
120
|
+
if first.respond_to?(:succ)
|
121
|
+
to_a.at_rand
|
122
|
+
elsif Numeric===first && Numeric===last
|
123
|
+
number = (last - first) * Random.number + first
|
124
|
+
(number == last && exclude_end?) ? first : number
|
125
|
+
else
|
126
|
+
nil
|
127
|
+
end
|
112
128
|
end
|
113
129
|
|
114
130
|
end
|
data/lib/more/facets/roman.rb
CHANGED
@@ -1,174 +1,67 @@
|
|
1
|
-
|
2
|
-
# Roman Numerals
|
3
|
-
#
|
4
|
-
# = SYNOPSIS:
|
5
|
-
# Generates roman numerals from integers and vice-versa.
|
6
|
-
#
|
7
|
-
# = NOTES:
|
8
|
-
# A response to Ruby Quiz of the Week #22 - Roman Numerals [ruby-talk:132925]
|
9
|
-
#
|
10
|
-
# = AUTHORS:
|
11
|
-
# - Dave Burt <dave at burt.id.au>
|
12
|
-
# - Trans
|
13
|
-
|
14
|
-
module English #:nodoc:
|
15
|
-
|
16
|
-
# Contains methods to convert integers to roman numeral strings and vice-versa.
|
17
|
-
|
18
|
-
module RomanNumerals
|
19
|
-
|
20
|
-
# The largest integer representable as a roman
|
21
|
-
# numerable by this module.
|
22
|
-
|
23
|
-
MAX = 3999
|
24
|
-
|
25
|
-
# Stolen from O'Reilly's Perl Cookbook 6.23. Regular Expression Grabbag.
|
26
|
-
|
27
|
-
REGEXP = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i
|
28
|
-
|
29
|
-
#
|
30
|
-
|
31
|
-
SYMBOLS = [ "M", "D", "C", "L", "X", "V", "I" ]
|
32
|
-
NUMBERS = [ 1000, 500, 100, 50, 10, 5, 1 ]
|
33
|
-
|
34
|
-
|
35
|
-
# Maps roman numeral digits to their integer values.
|
36
|
-
# {
|
37
|
-
# 'I' => 1,
|
38
|
-
# 'V' => 5,
|
39
|
-
# 'X' => 10,
|
40
|
-
# 'L' => 50,
|
41
|
-
# 'C' => 100,
|
42
|
-
# 'D' => 500,
|
43
|
-
# 'M' => 1000,
|
44
|
-
# }
|
45
|
-
|
46
|
-
TABLE = Hash[*SYMBOLS.zip(NUMBERS).flatten]
|
1
|
+
class Integer
|
47
2
|
|
48
3
|
#
|
49
|
-
|
50
|
-
PAIR_SYMBOLS = [ "CM", "CD", "XC", "XL", "IX", "IV", "I" ]
|
51
|
-
PAIR_NUMBERS = [ 900, 400, 90, 40, 9, 4, 1 ]
|
52
|
-
|
53
|
-
# {
|
54
|
-
# 'CM' => 900,
|
55
|
-
# 'CD' => 400,
|
56
|
-
# 'XC' => 90,
|
57
|
-
# 'XL' => 40,
|
58
|
-
# 'IX' => 9,
|
59
|
-
# 'IV' => 4
|
60
|
-
# }
|
61
|
-
|
62
|
-
PAIR_TABLE = Hash[*PAIR_SYMBOLS.zip(PAIR_NUMBERS).flatten]
|
4
|
+
ROMAN_MAX = 3999
|
63
5
|
|
64
6
|
#
|
7
|
+
ROMAN_VALUES = [
|
8
|
+
["M", 1000],
|
9
|
+
["CM", 900],
|
10
|
+
["D", 500],
|
11
|
+
["CD", 400],
|
12
|
+
["C", 100],
|
13
|
+
["XC", 90],
|
14
|
+
["L", 50],
|
15
|
+
["XL", 40],
|
16
|
+
["X", 10],
|
17
|
+
["IX", 9],
|
18
|
+
["V", 5],
|
19
|
+
["IV", 4],
|
20
|
+
["I", 1]
|
21
|
+
]
|
65
22
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
return nil if integer < 0 || integer > MAX
|
75
|
-
|
76
|
-
r = integer # remainder
|
77
|
-
y = '' # result
|
78
|
-
|
79
|
-
NUMBERS.each do |n|
|
80
|
-
while r >= n
|
81
|
-
r -= n
|
82
|
-
y += LOOKUP[n]
|
83
|
-
end
|
84
|
-
break if r <= 0
|
85
|
-
end
|
86
|
-
|
87
|
-
return y
|
88
|
-
end
|
89
|
-
|
90
|
-
alias_method :roman, :from_integer
|
91
|
-
|
92
|
-
# Converts +roman_string+, a roman numeral, to an integer
|
93
|
-
|
94
|
-
def to_integer(roman_string)
|
95
|
-
return nil unless roman_string.is_roman_numeral?
|
96
|
-
|
97
|
-
l = nil # last
|
98
|
-
i = 0 # integer result
|
99
|
-
|
100
|
-
c = roman_string.to_s.upcase.split(//).reverse
|
101
|
-
|
102
|
-
c.each do |d|
|
103
|
-
if v = TABLE[d]
|
104
|
-
if l && l > v
|
105
|
-
i -= v
|
106
|
-
else
|
107
|
-
i += v
|
108
|
-
end
|
109
|
-
l = v
|
110
|
-
end
|
23
|
+
# Converts this integer to a roman numeral.
|
24
|
+
def roman
|
25
|
+
int = self
|
26
|
+
#return nil if integer > ROMAN_MAX
|
27
|
+
return "-#{(-int).roman}" if int < 0
|
28
|
+
return "" if int == 0
|
29
|
+
ROMAN_VALUES.each do |(i, v)|
|
30
|
+
return(i + (int-v).roman) if v <= int
|
111
31
|
end
|
112
|
-
|
113
|
-
return i
|
114
|
-
end
|
115
|
-
|
116
|
-
alias_method :arabic, :to_integer
|
117
|
-
|
118
|
-
# Returns true iif +string+ is a roman numeral.
|
119
|
-
|
120
|
-
def is_roman_numeral?(string)
|
121
|
-
REGEXP =~ string
|
122
|
-
end
|
123
|
-
|
124
32
|
end
|
125
33
|
|
126
34
|
end
|
127
35
|
|
128
|
-
end # module English
|
129
|
-
|
130
36
|
|
131
|
-
class
|
132
|
-
|
133
|
-
def roman
|
134
|
-
English::RomanNumerals.roman(self) || ''
|
135
|
-
end
|
136
|
-
|
137
|
-
# Converts this integer to a roman numeral.
|
138
|
-
|
139
|
-
def to_s_roman
|
140
|
-
English::RomanNumerals.from_integer(self) || ''
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
37
|
+
class String
|
144
38
|
|
39
|
+
# Taken from O'Reilly's Perl Cookbook 6.23. Regular Expression Grabbag.
|
40
|
+
ROMAN = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i
|
145
41
|
|
146
|
-
|
42
|
+
#
|
43
|
+
ROMAN_VALUES = Integer::ROMAN_VALUES.inject({}){ |h,(r,a)| h[r] = a; h }
|
147
44
|
|
148
|
-
# Considers string a
|
45
|
+
# Considers string a Roman numeral numeral,
|
149
46
|
# and converts it to the corresponding integer.
|
150
|
-
|
151
|
-
|
152
|
-
|
47
|
+
def roman
|
48
|
+
roman = self
|
49
|
+
raise unless roman?
|
50
|
+
last = roman[-1,1]
|
51
|
+
roman.reverse.split('').inject(0) do |result, c|
|
52
|
+
if ROMAN_VALUES[c] < ROMAN_VALUES[last]
|
53
|
+
result -= ROMAN_VALUES[c]
|
54
|
+
else
|
55
|
+
last = c
|
56
|
+
result += ROMAN_VALUES[c]
|
57
|
+
end
|
58
|
+
end
|
153
59
|
end
|
154
60
|
|
155
|
-
# Returns true iif the subject is a
|
156
|
-
|
157
|
-
|
158
|
-
English::RomanNumerals.is_roman_numeral?(self)
|
61
|
+
# Returns true iif the subject is a valid Roman numeral.
|
62
|
+
def roman?
|
63
|
+
ROMAN =~ self
|
159
64
|
end
|
160
65
|
|
161
66
|
end
|
162
67
|
|
163
|
-
|
164
|
-
# # Quiz solution: filter that swaps roman and arabic numbers
|
165
|
-
# if __FILE__ == $0
|
166
|
-
# ARGF.each do |line|
|
167
|
-
# line.chomp!
|
168
|
-
# if line.is_roman_numeral?
|
169
|
-
# puts line.to_i_roman
|
170
|
-
# else
|
171
|
-
# puts line.to_i.to_s_roman
|
172
|
-
# end
|
173
|
-
# end
|
174
|
-
# end
|