------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--