nog meer roman numerals

Gepubliceerd op: 17.XI.2005 04:29 CET
Categorieën: ruby

Oh, we willen natuurlijk ook de andere kant op kunnen! Voeg het volgende toe aan de uitgebreide Fixnum:

class Fixnum

  @@ROMAN_HASH = Hash[*@@ROMAN_DIGITS.map{|a,b|[b,a]}.flatten]

  def self.from_roman(txt)
    result, last = 0, 0
    txt.upcase.reverse.each_byte do |c|
      n = @@ROMAN_HASH[c.chr] or raise "'#{c.chr}' is not a valid roman digit"
      result += n < last ? -n : n
      last = n
    end
    result
  end
end

En nu kan je met Fixnum.from_roman('MCMLXXII') weer terug naar 1972!

Danny @ 3 dagen

Kan mooier.

Waarom niet de String class hacken zodat je kunt zeggen: 'MCMLXXII'.from_roman()? Sowieso is de methodnaam to_roman hier niet helemaal terecht, je converteert immers van roman naar een normaal getal?

blog.dannynet.net

Remco @ 4 dagen

Ach daar moet natuurlijk Fixnum.from_roman('MCMLXXII') staan ipv Fixnum.to_roman('MCMLXXII'). De code klopt alleen m’n enthousiasme daarna spoort niet.

De String class molesteren kan natuurlijk ook:

class String
  @@ROMAN_HASH = {
    'M' => 1000, 'D' => 500, 'C' => 100, 'L' => 50,
    'X' => 10, 'V' => 5, 'I' => 1
  }

  alias old_to_i to_i

  def to_i
    return old_to_i unless self =~ /^[MDCLXVI]+$/i

    result, last = 0, 0
    upcase.reverse.each_byte do |c|
      n = @@ROMAN_HASH[c.chr]
      result += n < last ? -n : n
      last = n
    end
    result
  end
end

'MCMLXXII'.to_i geeft nu 1972!