------ art_1044_19209162.1192980378076
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Hello,
Here is my solution to the quiz. First I used smaller classes to simplify
TimeWindow:
# Class to store a single time range defined by a start/end
class TimeRange
# Each Input in form of "HHMM"
def initialize(start_str, end_str)
@start tart_str.to_i
@end nd_str.to_i
end
attr_reader :start, :end
end
# Represents a single time period for particular days and times
# A time window may contain several of these frames
class TimeFrame
# Days - Bitmask of 7 fields (Sun @ 0, Mon @ 1, Tues @ 2, etc)
# Time range - List of start/end time ranges defining the time frame
def initialize(days, time_ranges)
@days ays
@time_ranges ime_ranges
end
# Does the given Time match this Time Frame?
def include?(time)
if @days[time.wday]
# If no times then days matching is good enough
return true if @time_ranges.size 0
# Check time range(s)
for time_range in @time_ranges
time_n ime.hour * 100 + time.min
return true if time_n > ime_range.start and
time_n < time_range.end
end
end
false
end
end
The main class then simply parses the time window string at startup, saving
each individual time window to memory. Then the include? method iterates
through those time windows to determine if a particular time is in the
window:
# Defines a time window spanning multiple days and time ranges
class TimeWindow
Days "Sun", "Mon", "Tues", "Wed", "Thu", "Fri", "Sat"]
# Constructor accepting a string as defined in ruby quiz description
def initialize(time_window)
@timeframes ]
for group in time_window.split(";")
days, times rray.new(7, false), []
for item in group.split(" ")
# Range of values?
if item.include?("-")
# Yes, Figure out if range is days or times
range tem.split("-")
if Days.include?(range[0])
set_day_range(days, range[0], range[1])
else
times << TimeRange.new(range[0], range[1])
end
else
days[Days.index(item)] rue if Days.include?(item)
end
end
@timeframes << TimeFrame.new(days, times)
end
end
# Set days in given range in the input array
# Inputs: days - List of days in the time window
# start_day, end_day - Day range to add to the window
def set_day_range(days, start_day, end_day)
pos Days.index(start_day)
while pos ! Days.index(end_day) + 1) % 7
days[pos] rue
pos pos + 1) % 7
end
end
# Does the given Time match this time window?
def include?(time)
for time_frame in @timeframes
return true if time_frame.include?(time)
end
return (@timeframes.size 0) # Empty time string matches all times
end
private :set_day_range
end
Fortunately it passes all of the tests :)
A pastie is available here: http://pastie.caboo.se/109346
Thanks,
Justin
On 10/19/07, Ruby Quiz <james / grayproductions.net> 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.rubyquiz.com/
>
> 3. Enjoy!
>
> Suggestion: A [QUIZ] in the subject of emails about the problem helps
> everyone
> on Ruby Talk follow the discussion. Please reply to the original quiz
> message,
> if you can.
>
>
> - - - - - - - - - - - - - - - - - - - -
>
> by Brian Candler
>
> Write a Ruby class which can tell you whether the current time (or any
> given
> time) is within a particular "time window". Time windows are defined by
> strings
> in the following format:
>
> # 0700-0900 # every day between these times
> # Sat Sun # all day Sat and Sun, no other
> times
> # Sat Sun 0700-0900 # 0700-0900 on Sat and Sun only
> # Mon-Fri 0700-0900 # 0700-0900 on Monday to Friday
> only
> # Mon-Fri 0700-0900; Sat Sun # ditto plus all day Sat and
> Sun
> # Fri-Mon 0700-0900 # 0700-0900 on Fri Sat Sun Mon
> # Sat 0700-0800; Sun 0800-0900 # 0700-0800 on Sat, plus
> 0800-0900 on Sun
>
> Time ranges should exclude the upper bound, i.e. 0700-0900 is 07:00:00 to
> 08:59:59. An empty time window means "all times everyday". Here are some
> test
> cases to make it clearer:
>
> class TestTimeWindow < Test::Unit::TestCase
> def test_window_1
> w imeWindow.new("Sat-Sun; Mon Wed 0700-0900; Thu 0700-0900
> 1000-1200")
>
> assert ! w.include?(Time.mktime(2007,9,25,8,0,0)) # Tue
> assert w.include?(Time.mktime(2007,9,26,8,0,0)) # Wed
> assert ! w.include?(Time.mktime(2007,9,26,11,0,0))
> assert ! w.include?(Time.mktime(2007,9,27,6,59,59)) # Thu
> assert w.include?(Time.mktime(2007,9,27,7,0,0))
> assert w.include?(Time.mktime(2007,9,27,8,59,59))
> assert ! w.include?(Time.mktime(2007,9,27,9,0,0))
> assert w.include?(Time.mktime(2007,9,27,11,0,0))
> assert w.include?(Time.mktime(2007,9,29,11,0,0)) # Sat
> assert w.include?(Time.mktime(2007,9,29,0,0,0))
> assert w.include?(Time.mktime(2007,9,29,23,59,59))
> end
>
> def test_window_2
> w imeWindow.new("Fri-Mon")
> assert ! w.include?(Time.mktime(2007,9,27)) # Thu
> assert w.include?(Time.mktime(2007,9,28))
> assert w.include?(Time.mktime(2007,9,29))
> assert w.include?(Time.mktime(2007,9,30))
> assert w.include?(Time.mktime(2007,10,1))
> assert ! w.include?(Time.mktime(2007,10,2)) # Tue
> end
>
> def test_window_nil
> w DS::TimeWindow.new("")
> assert w.include?(Time.mktime(2007,9,25,1,2,3)) # all
> times
> end
> end
>
>
------ art_1044_19209162.1192980378076--