Another solution for Time Window quiz:

I considered only when input has day ranges in ascending order ("Mon
Fri-Sun" or "Fri-Sun Mon", but not "Fri-Mon") and the first day of the
week is Monday.


class TimeWindow

  Days = { "Mon" => 0, "Tue" => 1, "Wed" => 2, "Thu" => 3, "Fri" => 4,
"Sat" => 5, "Sun" => 6}

  def initialize (window)
    @window = window
    @ranges = []
    parse_window
  end

  def include? (time)
    hour = time.strftime("%H%M").to_i
    day = time.strftime("%w").to_i
    req = (day-1)*10000+hour
    puts "#{req}"
    result = false
    @ranges.each{ |range|
      if range[0] <= req && req < range[1]
        result = true
      end
    }
    result
  end

  private

  #Parse the input
  def parse_window
    regex = /((?:Mon[ -]?|Tue[ -]?|Wed[ -]?|Thu[ -]?|Fri[ -]?|Sat[
-]?|Sun[ -]?)+)?((?:[012]\d[0-6]\d-[012]\d[0-6]\d[ ]?)+)?/
    @window.split(";").each { |window|
      window.strip!
      match = regex.match(window)

      # it has days
      if match[1]
        days = parse_days match[1]
      else
        days = [[0,6]]       # everyday
      end

      # it has hours
      if match[2]
        time = parse_time match[2]
      else
        time = [[0,2400]]   # all day
      end

      days.each {|dr|
        time.each {|tr|
          @ranges << [dr[0]*10000+tr[0], dr[1]*10000+tr[1]]
        }
      }
    }
  end

  def parse_days (days)
    result = []
    days.scan(/(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun)-(Mon|Tue|Wed|Thu|Fri|Sat|Sun)|(Mon|Tue|Wed|Thu|Fri|Sat|Sun))/)
{
      if $3                # it's just one day
        result << [Days[$3],Days[$3]]
      else                # it's a range
        result << [Days[$1],Days[$2]]
      end
    }
    result
  end

  def parse_time (time)
    result = []
    time.scan(/([012]\d[0-6]\d)-([012]\d[0-6]\d)/) {
      result << [$1.to_i, $2.to_i]
    }
    result
  end
end