On Fri, 19 Oct 2007 21:14:00 +0900, Ruby Quiz 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 = TimeWindow.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 = TimeWindow.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 = RDS::TimeWindow.new("") > assert w.include?(Time.mktime(2007,9,25,1,2,3)) # all times > end > end #!/usr/bin/env ruby class TimeWindow DAYNAMES=%w[Sun Mon Tue Wed Thu Fri Sat] DAYNAME=%r{Sun|Mon|Tue|Wed|Thu|Fri|Sat} TIME=%r{[0-9]+} def initialize string string = " " if string == "" #make an empty string match everythingworking around the way clauses are split #splitting an empty string gives an empty array (i.e. no clauses) #splitting a " " gives a single clause with no day names (so all are used) and no times (so all are used) @myarray=Array.new(7){[]} #different clauses are split by semicolons string.split(/\s*;\s*/).each do |clause| #find the days that this clause applies to curdays=[] clause.scan(/(#{DAYNAME})(?:(?=\s)|$)|(#{DAYNAME})-(#{DAYNAME})/) do |single,start,finish| single &&= DAYNAMES.index(single) start &&= DAYNAMES.index(start) finish &&= DAYNAMES.index(finish) curdays << single if single if start and finish (start..finish).each{|x| curdays << x} if start<finish (start..6).each{|x| curdays << x} if finish<start (0..finish).each{|x| curdays << x} if finish<start end end #all days if no day names were given curdays=(0..6).to_a if curdays==[] #find the times that this clause applies to found=false clause.scan(/(#{TIME})-(#{TIME})/) do |start,finish| found=true curdays.each do |day| @myarray[day] << [start,finish] end end #all times if none were given if not found curdays.each {|day| @myarray[day] << ["0000","2400"]} end end end def include? time matchday=time.wday matchtime="%02d%02d" % [time.hour,time.min] @myarray[matchday].any?{|start,finish| start<=matchtime && matchtime<finish} end alias_method :===, :include? end -- Ken Bloom. PhD candidate. Linguistic Cognition Laboratory. Department of Computer Science. Illinois Institute of Technology. http://www.iit.edu/~kbloom1/