> 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. Well, I came up with two solutions... But I wasn't able to complete both of them. Here's the easier one; It splats ranges into arrays, flattens the whole mess, makes sure they are all integers, uniqs them, then joins them with pipes and embeds them in a regular expression. It allows an arbitrary number of leading zeros, and anchors to the start and end of the line. I didn't really spend any time on it, so I didn't bother with negative values; I'm not sure what they would do. def Regexp.build(*args) # splat ranges into arrays of numbers, convert to integers, # remove duplicates, and sort the list numbers = args.map{|n| [*n] }.flatten.map{|n| n.to_i } # create a range from the list of numbers /^0*(?:#{numbers.uniq.join("|")})$/ end My other solution was a lot better; I just got too frustrated trying to make it. I kept thinking I had it working, then a border case would pop up that didn't work properly. So, I'll submit the idea for inspection, maybe someone will pick it up and run with it. Here's the basic algorithm: 1. break the range up into regexp friendly sections, like this: (23..1024) => 23..29, 30..99, 100..999, 1000..1019, 1020..1024 2. convert each range into a string regexp: 23..29 => "2[3-9]" 30..99 => "[3-9]\\d" 100..999 => "[1-9]\\d\\d" 1000..1019 => "10[01]\\d" 1020..1024 => "102[0-4]" 3. join them all together /^0*(?:2[3-9]|[3-9]\d|[1-9]\d\d|10[01]\d|102[0-4])$/ That gets the most compact regexp for each range. But I've been beating my head against the wall getting it programmed. I'll keep thinking about it, but... Anyone? cheers, Mark