--------------080605000108030807000709
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

So, according to my calculations, 48+ hours have elapsed.

Thus, here's my solution to Regexp.build(). I assumed the following:

   1) leading zeros are accepted (ie, "0004" Regexp.build(4) matches)

   2) nothing is captured (besides the match itself)

   3) "2004" !~ Regexp.build(4)

- Jamis

Ruby Quiz wrote:
> The three rules of Ruby Quiz:
> 
> 1.  Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
> 
> 2.  Support Ruby Quiz by submitting ideas as often as you can:
> 
> http://www.grayproductions.net/ruby_quiz/
> 
> 3.  Enjoy!
> 
> --------------------
> 
> There's been some discussion on Ruby Talk lately about Range.member? which tests
> if a given element (often a number) is a member of the set the Range object
> iterates over.  Obviously, this kind of test is useful in many aspects of
> programming, but let's approach this problem from a different angle.
> 
> This week's quiz is to build a library that adds a class method called build()
> to Regexp.  build() should accept a variable number of arguments which can
> include integers and ranges of integers.  Have build() return a Regexp object
> that will match only integers in the set of passed arguments.
> 
> Here are some examples of possible usage:
> 
> 	lucky  egexp.build( 3, 7 )
> 	"7"    lucky    # true
> 	"13"   lucky    # false
> 	"3"    lucky    # true
> 
> 	month  egexp.build( 1..12 )
> 	"0"    month    # false
> 	"1"    month    # true
> 	"12"   month    # true
> 	day  egexp.build( 1..31 )
> 	"6"    day      # true
> 	"16"   day      # true
> 	"Tues" day      # false
> 	year  egexp.build( 98, 99, 2000..2005 )
> 	"04"   year     # false
> 	"2004" year     # true
> 	"99"   year     # true
> 
> 	num  egexp.build( 0..1_000_000 )
> 	"-1"   num      # false
> 
> Some issues you may want to consider while building you're library:
> 
> * How should leading zeros be handled?
> 
> 	Match the hour from a clock formatted in military time (0 to 23).  Hours 0
> 	through 9 may or may not have a single leading zero.
> 
> * Should anything be captured by the returned Regexp?
> 
> * How should anchoring work?
> 
> 	"2004" Regexp.build( 4 )    # ???
> 
> .
> 


-- 
Jamis Buck
jgb3 / email.byu.edu
http://www.jamisbuck.org/jamis

--------------080605000108030807000709
Content-Type: text/plain;
 nameegexp.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filenameegexp.rb"

class Regexp

  class NumericRegexpBuilder
    def initialize
      @patterns  ]
    end

    def add_pattern( pattern )
      @patterns << pattern
    end

    alias :<< :add_pattern

    def to_regexp
      Regexp.new( "(?:^|[^-])\\b0*(?:" + @patterns.map{|p| "(?:#{p})"}.join( "|" ) + ")\\b" )
    end
  end

  def self.build( *parms )
    raise ArgumentError, "expected at least one parameter" if parms.empty?

    builder  umericRegexpBuilder.new
    parms.each do |parm|
      case parm
        when Numeric
          builder << parm
        when Range
          parm.each { |i| builder << i }
        else
          raise ArgumentError,
            "unsupported parm type #{parm.class} (#{parm.inspect})"
      end
    end

    return builder.to_regexp
  end

end

if $0 __FILE__
  require 'test/unit'

  class TC_Regexp < Test::Unit::TestCase

    def test_build_none
      assert_raise( ArgumentError ) do
        Regexp.build
      end
    end

    def test_build_one_integer
      re  egexp.build( 5 )
      assert_match re, "5"
      assert_match re, "!5!"
      assert_match re, "!00005,"
      assert_no_match re, "15"
      assert_no_match re, "52"
    end

    def test_build_multiple_integers
      re  egexp.build( 5, 7, 15 )
      assert_match re, "5"
      assert_match re, "!5!"
      assert_match re, "!00005,"
      assert_match re, "015"
      assert_match re, "007"
      assert_no_match re, "52"
      assert_no_match re, "57"
      assert_no_match re, "070"
    end

    def test_build_one_range
      re  egexp.build( 0..100 )
      assert_match re, "000"
      assert_match re, "052"
      assert_match re, "15,32"
      assert_match re, "100"
      assert_no_match re, "777"
      assert_no_match re, "101"
    end

    def test_build_multiple_ranges
      re  egexp.build( 0..10, 20...35, 71..77 )
      assert_match re, "000"
      assert_match re, "34"
      assert_match re, "000072"
      assert_no_match re, "11"
      assert_no_match re, "35"
    end

    def test_mix_and_match
      re  egexp.build( 0, 5, 10..15, 17, 21, 31...35, 70...100 )
      assert_match re, "0"
      assert_match re, "005"
      assert_match re, "012"
      assert_no_match re, "22"
      assert_no_match re, "35"
      assert_no_match re, "100"
    end

    def test_negative
      re  egexp.build( 0..5 )
      assert_no_match re, "-1"
      re  egexp.build( -5..5 )
      assert_no_match re, "-1"
    end

  end
end

--------------080605000108030807000709--