------art_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 = 0.0254 m
1 l  = 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 = { "Y" => 10**24, "Z" => 10**21, "E" => 10**18, "P" =>
10**15, "T" => 10**12,
      "G" => 10**9, "M" => 1_000_000, "k" => 1000, "h" => 100, "D" => 10,
      "d" => 0.1, "c" => 0.01, "m" => 0.001, " => 0.000_001, "n" =>
10**-9, "p" => 10**-12,
      "f" => 10**-15, "a" => 10**-18, "z"=> 10**-21, "y" => 10**-24def parse_line line
      return if /^\s*#/ === line || line.strip.empty?
      line = line.strip.sub /#.*/, ""
      case line
      when /^use SI prefixes for /
	add_si_units line.split[4..-1]
      else
	add_conversion *line.split
      end
    end

    def traverse &blk
      @c.each do | unit, conversion_hash |
	_traverse unit, conversion_hash, [ unit ], &blk
      end
    end
    private
    def add_conversion lhs_value, lhs_unit, equal_dummy, rhs_value, rhs_unit
      @c[ lhs_unit ][ rhs_unit ] = Float( rhs_value ) / Float( lhs_value )
      @c[ rhs_unit ][ lhs_unit ] = Float( lhs_value ) / Float( rhs_value )
    end

    def add_si_units units
      units.each do |unit|
	add_si_unit_for unit
      end
    end

    def add_si_unit_for unit
      SIUnits.each do | prefix, conversion |
	@c[ prefix + unit ][ unit ] = conversion
	@c[ unit ][ prefix + unit ] = 1 / conversion
      end
    end

    def initialize
      @c = Hash::new{ | h, k | h[ k ] = { } }
    end

    def _traverse src_unit, unit_conversions, traversed_units, f=1.0, &blk
      unit_conversions.each do | new_unit, conversion |
	next if traversed_units.include? new_unit
	blk.call src_unit, new_unit, f * conversion
	_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 dynamically
  #  by means of exploring "units.txt"
  #
  class ProxyClass
    # syntactic sugar
    def to; self end
    alias_method :as, :to

    private
    def initialize value
      @value = value
    end
  end

  ProxyClasses = {} # maps units to their proxy classes
  def method_missing unit_name
    pc = ProxyClasses[ unit_name.to_s ] || super( unit_name )
    pc::new self
  end

  conversions = 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 ] ||= 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.
-- 
Ne baisse jamais la tů’e, tu ne verrais plus les Ů’oiles.

Robert Dober ;)

------art_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------art_29100_1594400.1227137618515--