This is one of the problems that looks easier than it is
(at least to me). My solution handles input in form of day
abbreviations, full day names and integers as described in
the quiz. It raises an ArgumentError for all other inputs.
Further more my solution wraps around:
puts DayRange.new('Monday', 'Sun', 5, 2, 6)
results in "Fri-Tue" instead of "Mon, Tue, Fri-Sun"
(this can be easily switched of by deleting the last two
lines of the initialize method).
I also included Enumerable and provided an each method, but
i'm not sure if this is really helpful because each iterates
over each day not each range (would that be more helpful?).
Well, here it is:
--------------------------------------------------------------
require 'date'
class DayRange
include Enumerable
def initialize *days
@days = []
days.map do |d|
day = Date::DAYNAMES.index(d) || Date::ABBR_DAYNAMES.index(d)
raise ArgumentError, d.to_s unless day || (1..7).include?(d.to_i)
day ? day.nonzero? || 7 : d.to_i
end.uniq.sort.each do |d|
next @days << [d] if @days.empty? || d != @days.last.last + 1
@days.last << d
end
p @days
return unless @days.first.first == 1 && @days.last.last == 7
@days.last.concat(@days.shift) if @days.size > 1
end
def each
@days.flatten.each{|d| yield d}
end
def to_s
@days.map do |r|
first = Date::ABBR_DAYNAMES[r.first % 7]
last = Date::ABBR_DAYNAMES[r.last % 7]
next "#{first}, #{last}" if r.size == 2
r.size > 2 ? "#{first}-#{last}" : first
end * ', '
end
end
puts DayRange.new(1, 2, 3, 4, 5, 6, 7) #=> Mon-Sun
puts DayRange.new('Monday', 'Sun', 5, 2, 6) #=> Fri-Tue
puts DayRange.new(2, 6, 'Friday', 'Sun') #=> Tue, Fri-Sun
dr = DayRange.new(2, 6, 'Friday', 'Sun')
puts dr.map{|d| Date::DAYNAMES[d % 7]} * ', '
#=> Tuesday, Friday, Saturday, Sunday
-----------------------------------------------------------------
cheers
Simon