------=_Part_29100_1594400.1227137618515
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
Well time is difficult to get but I just had to supply a Ruby Quiz
submission *again*.
Was so much fun. Tried to implemnt Tom's syntax driven by a data file
(tiny :(, see above)
# file: units.txt
#
# Units data file for Ruby Quiz #183
#
# -----------------------------------
#
1 in =3D 0.0254 m
1 l =3D 0.001 m3
use SI prefixes for m g l m3
_____________________________________________
# file: units.rb
module Conversion
#
# A primitive parser to create the conversion data structure, syntax
checks are
# omitted to shorten the solution ;).
#
class LineParser
SIUnits =3D { "Y" =3D> 10**24, "Z" =3D> 10**21, "E" =3D> 10**18, "P" =
=3D>
10**15, "T" =3D> 10**12,
"G" =3D> 10**9, "M" =3D> 1_000_000, "k" =3D> 1000, "h" =3D> 100, "D" =
=3D> 10,
"d" =3D> 0.1, "c" =3D> 0.01, "m" =3D> 0.001, "=B5" =3D> 0.000_001, "n=
" =3D>
10**-9, "p" =3D> 10**-12,
"f" =3D> 10**-15, "a" =3D> 10**-18, "z"=3D> 10**-21, "y" =3D> 10**-24=
}
def parse_line line
return if /^\s*#/ =3D=3D=3D line || line.strip.empty?
line =3D line.strip.sub /#.*/, ""
case line
when /^use SI prefixes for /
=09add_si_units line.split[4..-1]
else
=09add_conversion *line.split
end
end
def traverse &blk
@c.each do | unit, conversion_hash |
=09_traverse unit, conversion_hash, [ unit ], &blk
end
end
private
def add_conversion lhs_value, lhs_unit, equal_dummy, rhs_value, rhs_uni=
t
@c[ lhs_unit ][ rhs_unit ] =3D Float( rhs_value ) / Float( lhs_value =
)
@c[ rhs_unit ][ lhs_unit ] =3D Float( lhs_value ) / Float( rhs_value =
)
end
def add_si_units units
units.each do |unit|
=09add_si_unit_for unit
end
end
def add_si_unit_for unit
SIUnits.each do | prefix, conversion |
=09@c[ prefix + unit ][ unit ] =3D conversion
=09@c[ unit ][ prefix + unit ] =3D 1 / conversion
end
end
def initialize
@c =3D Hash::new{ | h, k | h[ k ] =3D { } }
end
def _traverse src_unit, unit_conversions, traversed_units, f=3D1.0, &bl=
k
unit_conversions.each do | new_unit, conversion |
=09next if traversed_units.include? new_unit
=09blk.call src_unit, new_unit, f * conversion
=09_traverse src_unit, @c[ new_unit ], traversed_units + [ new_unit ], f
* conversion, &blk
end
end
end
#
# Will be subclassed for each unit.
# Each such sublcass will than get all conversion methods defined dynami=
cally
# by means of exploring "units.txt"
#
class ProxyClass
# syntactic sugar
def to; self end
alias_method :as, :to
private
def initialize value
@value =3D value
end
end
ProxyClasses =3D {} # maps units to their proxy classes
def method_missing unit_name
pc =3D ProxyClasses[ unit_name.to_s ] || super( unit_name )
pc::new self
end
conversions =3D LineParser::new
File::open "units.txt" do | f |
f.each do | line |
conversions.parse_line line
end
end
conversions.traverse do | src_unit, tgt_unit, conversion |
( ProxyClasses[ src_unit ] ||=3D Class::new ProxyClass ).module_eval do
define_method tgt_unit do (@value * conversion).to_s + tgt_unit end
end
end
end
class Integer
include Conversion
end
class Float
include Conversion
end
_________________________________________________________________
# file: test-solution.rb
require 'units'
require 'test/unit'
class Test183_01 < Test::Unit::TestCase
def test_001_simple
assert_equal "25.4mm", 1.0.in.to.mm
assert_equal "1.0mm", 0.001.m.to.mm
assert_equal "0.0393700787401575in", 1.mm.in
assert_equal "39370.0787401575in", 1.km.as.in
assert_equal "0.001m3", 1.0.l.as.m3
end
end
Thx for the quiz.
--=20
Ne baisse jamais la t=EAte, tu ne verrais plus les =E9toiles.
Robert Dober ;)
------=_Part_29100_1594400.1227137618515
Content-Type: application/x-gzip; name=183-robert-dober.tgz
Content-Transfer-Encoding: base64
X-Attachment-Id: f_fnqm13g60
Content-Disposition: attachment; filename=183-robert-dober.tgz
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
WgAoAAA=
------=_Part_29100_1594400.1227137618515--