require 'test/unit'
require 'test/unit/ui/console/testrunner'
module Enumerable
def in?(candidate)
any? {|any| any.in? candidate}
end
end
class Fixnum
def in?(candidate)
equal? candidate
end
end
class Range
def in?(candidate)
include? candidate
end
end
class BuildRegexp
GUARD = /^[0123456789]+$/
def initialize(candidates)
@candidates = candidates
end
def =~(candidate)
GUARD =~ candidate && (@candidates.in? candidate.to_i)
end
end
class Regexp
def self.build(*candidates)
BuildRegexp.new(candidates)
end
end
class BuildTest < Test::Unit::TestCase
def test_lucky()
lucky = Regexp.build(3,7)
assert('7' =~ lucky)
assert(!('13' =~ lucky))
assert('3' =~ lucky)
end
def test_month()
month = Regexp.build(1..12)
assert(!('0' =~ month))
assert('1' =~ month)
assert('12' =~ month)
end
def test_day()
day = Regexp.build(1..31)
assert('6' =~ day)
assert('16' =~ day)
assert(!('Tues' =~ day))
end
def test_year()
year = Regexp.build(98,99,2000..2005)
assert(!('04' =~ year))
assert('2004' =~ year)
assert('98' =~ year)
end
def test_num()
num = Regexp.build(0..1_000_000)
assert(!('-1' =~ num))
end
end
Test::Unit::UI::Console::TestRunner.new(BuildTest.suite()).start()
Of course, we excitedly looked up the answer in the book and were shocked. Their final answer was longer and harder to understand. Our code uses less of the regular expression class. In fact, we only used it as a guard to make sure we could convert the input to a number. We also made heavy use of polymorphism and duck typing(in?, =~). As you can see the code is very short.
The quiz was to build a Regexp to handle any list or range of numbers. The tests are taken exactly from the book and of course, we wrote them first. Well, actually, we wrote them at each stage. At one point, we were using Regexp extensively until we hit the last test. And that is when the change in requirements caused all of the code you see above.
How fun! We looked at each other and wondered, "Was our solution too simple?" We then laughed and said, "Nah." We were both proud for our simple and readable solution.