From: Eric Torreborre <etorreborre@yahoo.com>
Date: August 31, 2006 4:20:10 PM CDT
To: submission@rubyquiz.com
Subject: Please Forward: Ruby Quiz Submission (92)
Reply-To: Eric Torreborre <etorreborre@yahoo.com>Hi all,
This is my first submission to the quiz and I am very glad to do it! I used this quiz to introduce Ruby to my fellow workers for today's "Dojo" (see Référentiel des pratiques Agiles Agile Finland ry).
They found it a very gentle introduction to the language.
As for myself, I found a great interest in writing properly things down and then having a look at all other submissions, searching for better ways to do things.
Anyway, here is my submission, that goes around the following lines:
-use of rspec (behavior driven development) to write acceptance tests
-use of the Set class to know if days identifiers are correct
-extension of the Range class to split an array into an array of ranges for consecutive valuesHere's the code:
===========================
#day_range_spec.rbrequire "spec"
require "day_range"context "A new DayRange" do
specify "should accept a list of day numbers" do
DayRange.new([1, 2, 3])
endspecify "should accept a list of abbreviated day names" do
DayRange.new(%w{Mon Tue Fri})
endspecify "should accept a list of whole day names" do
DayRange.new(%w{Monday Tuesday Friday})
endspecify "should raise an argument error an invalid day number is inputed in the list" do
lambda {DayRange.new([1, 8])}.should_raise(ArgumentError)
endspecify "should raise an argument error an invalid abbreviated day is inputed in the list" do
lambda {DayRange.new(["bla"])}.should_raise(ArgumentError)
endspecify "should raise an argument error an invalid day name is inputed in the list" do
lambda {DayRange.new(["lunedi"])}.should_raise(ArgumentError)
end
endcontext "A week with a single day" do
specify "should return the day short name only" do
DayRange.new([7]).to_s.should_equal('Sun')
end
endcontext "An initialized DayRange" do
specify "should sort days starting with Monday" do
DayRange.new([3, 1]).to_s.should_equal('Mon, Wed')
end
endcontext "A week DayRange" do
specify "should represent three or more consecutive days by listing the first day followed by a hyphen (-), followed by the last day of the range" do
DayRange.new([1, 2, 3, 4, 5, 6, 7]).to_s.should_equal('Mon-Sun')
end
end
context "A week without Thursday and Friday" do
specify "should return 'Mon-Wed, Sat, Sun' (added hyphen)" do
DayRange.new([1, 2, 3, 6, 7]).to_s.should_equal('Mon-Wed, Sat, Sun')
end
end===========================
# day_range.rbrequire 'set'
require 'range'class DayRange
def initialize(daylist)
raise ArgumentError, "#{daylist.to_s} is not valid" unless Week.are_valid_identifiers?(daylist)
@days = Week.day_indexes(daylist)
enddef to_s
ranges = Range.split(@days)
ranges.collect{|r| Week.short_names_from_range(r)}.join(', ')
endend
class Week
DAYS = [[1, 'Mon', 'Monday'],
[2, 'Tue', 'Tuesday'],
[3, 'Wed', 'Wednesday'],
[4, 'Thu', 'Thursday'],
[5, 'Fri', 'Friday'],
[6, 'Sat', 'Saturday'],
[7, 'Sun', 'Sunday']]def self.are_valid_identifiers?(days)
return DAYS.flatten.to_set.superset?(days.to_set)
enddef self.day_indexes(daylist)
return DAYS.select{|d| !d.to_set.intersection(daylist.to_set).empty?}.collect{|d| d[0]}.sort!
enddef self.short_names_from_range(range)
if range.to_a.size == 1
return DAYS[range.first - 1][1]
elsif range.to_a.size == 2
return DAYS[range.first - 1][1] + ', ' + DAYS[range.last - 1][1]
else
return DAYS[range.first - 1][1] + '-' + DAYS[range.last - 1][1]
end
end
end===========================
#range_spec.rbrequire "spec"
require "range"context "A Range" do
specify "should split a [1] array in a 1..1 range" do
Range.split([1]).should_equal([1..1])
endspecify "should split a [1, 2] array in a 1..2 range" do
Range.split([1, 2]).should_equal([1..2])
endspecify "should split a [1, 2, 3] array in a 1..3 range" do
Range.split([1, 2, 3]).should_equal([1..3])
endspecify "should split a [1, 3] array in 2 ranges: [1..1, 3..3]" do
Range.split([1, 3]).should_equal([1..1, 3..3])
endspecify "should split a [1, 2, 4] array in 2 ranges: [1..2, 4..4]" do
Range.split([1, 2, 4]).should_equal([1..2, 4..4])
endend
#range.rb
class Range
def self.split(list)
list.inject() do |ranges, i|
last_range = ranges.last
if (last_range.nil? || i > last_range.last.next)
ranges << [i, i]
else
last_range[1] = i
end
ranges
end.collect{|r| r.first..r.last} # transform to Range objects
endend
--------------------------------------------------
Eric Torreborre
LTG - Product Manager
LEIRIOS
tel: 33(0)6.61.48.57.65/33(0)3.81.88.62.02
e-mail: etorreborre@yahoo.com
blog: http://etorreborre.blogspot.com
--------------------------------------------------
···
Begin forwarded message: