From: Ken Bloom Date: 2007-10-24T23:10:21+09:00 Subject: Re: [QUIZ] Time Window (#144) On Wed, 24 Oct 2007 10:04:56 +0900, James Koppel wrote: > Here's my solution. It converts a time window into an array of arrays of > ranges. Each range matches an interval of time (e.g.: 500..1700); each > subarray contains all the ranges for a given day. I then wrote the > simple Array#some method that returns true if the given predicate > returns true for at least one of its elements, which I used to write > TimeWindow#incude?. > > $days = {"Sun"=>0, > "Mon"=>1, > "Tue"=>2, > "Wed"=>3, > "Thu"=>4, > "Fri"=>5, > "Sat"=>6} I suggest using a constant rather than a global variable for this. You can put the constant in the TimeWindow class. > class Array > def some > each {|el| return true if yield el} > false > end > end This has already been discussed as being equal to Enumerable#any? > class TimeWindow > def initialize(win_str) > @times = ([nil]*7).map{[]} This is the same as Array.new(7){[]}, which is a more usual way to express this. > win_str << " " #In case of empty > win_str.split(/;/).each do |win| > days_str = win.match(/(((#{$days.keys.join('|')}|)( > |-)?)*)/)[0].strip days = [] > days_str.scan(/#{$days.keys.join('|')}/) do |day| > days << $days[day] > end > days_str.scan(/(#{$days.keys.join('|')})-(#{$days.keys.join ('|')})/) > do > a = $days[$1] > b = $days[$2] > days += (a..(b > a ? b : b+7)).to_a.map{|d|d%7} > end > days = (0..6).to_a if days.empty? > > times = [] > win.scan(/(\d{4})-(\d{4})/) do > times << (($1.to_i)...($2.to_i)) > end > times = [0..2400] if times.empty? > > days.each do |d| > times.each do |t| > @times[d] << t > end > end > end > > def include?(time) > @times[time.wday].some{|trange| trange === > (time.hour*100+time.min)} > end > end > end Looks generally like my solution. --Ken -- Ken Bloom. PhD candidate. Linguistic Cognition Laboratory. Department of Computer Science. Illinois Institute of Technology. http://www.iit.edu/~kbloom1/