The solutions for RPCFN 2 are now under judgement, so it’s the time to show my effort.
The problem was easy, but a little tricky: given a list of time of day, the program should find the average time.
The tricky part was to manage “am” and “pm” times, mapping them in date format: given “11:59am” and “12:00am”, then average time should be midnight.
My solution is based on the principle than if the range between “am” and “pm” times is under half a day, they are in the same day, otherwise a day leap occurs; this approach worked well, althought it needed a little bit of explanation in code, as noted by Chris himself
.
These are my spec:
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib]) require 'average_time_of_day' describe 'average_time_of_day' do context 'for "06:00pm" and "07:00pm"' do it 'should be "06:30pm"' do avg = average_time_of_day(["06:00pm", "07:00pm"]) avg.should == "06:30pm" end end context 'for "06:00pm", "07:00pm" and "08:00pm' do it 'should be "07:00pm"' do avg = average_time_of_day(["06:00pm", "07:00pm", "08:00pm"]) avg.should == "07:00pm" end end context 'for "06:41am", "06:51am" and "07:01am' do it 'should be "06:51am"' do avg = average_time_of_day(["06:41am", "06:51am", "07:01am"]) avg.should == "06:51am" end end context 'for "23:59pm" and "12:01am' do it 'should be "12:00am"' do avg = average_time_of_day(["23:59pm", "00:01am"]) avg.should == "12:00am" end end context 'for "11:51pm", "11:56pm", "12:01am", "12:06am" and "12:11am"' do it 'should be "12:01am"' do avg = average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"]) avg.should == "12:01am" end end context 'for "11:15pm", "12:03am", "11:30pm", "11:23pm", "11:48pm"' do it 'should be "11:35pm"' do avg = average_time_of_day(["11:15pm", "12:03am", "11:30pm", "11:23pm", "11:48pm"]) avg.should == "11:35pm" end end context 'for "05:15am", "06:03am", "05:30am", "05:23am", "05:48am"' do it 'should be "05:35am"' do avg = average_time_of_day(["05:15am", "06:03am", "05:30am", "05:23am", "05:48am"]) avg.should == "05:35am" end end context 'for "11:15am", "12:03pm", "11:30am", "11:23am", "11:48am"' do it 'should be "11:35am"' do avg = average_time_of_day(["11:15am", "12:03pm", "11:30am", "11:23am", "11:48am"]) avg.should == "11:35am" end end context 'for "6:00pm" and "6:00am' do it 'should be "12:00am"' do avg = average_time_of_day(["6:00pm", "6:00am"]) avg.should == "12:00am" end end context 'for "12:01am", "11:51pm", "11:56pm", "12:06am" and "12:11am"' do it 'should be "12:01am"' do avg = average_time_of_day(["12:01am", "11:51pm", "11:56pm", "12:06am", "12:11am"]) avg.should == "12:01am" end end end
and this are my code:
require 'time'
private
class Array
def to_sec
map {|t|t.to_f}
end
def avg
(size > 0) ? to_sec.inject(0.0){|sum,el| sum + el}/size : 0
end
end
class Time
def am?
hour < 12
end
def pm?
not am?
end
def to_s
strftime("%I:%M%p").downcase
end
end
DAY_IN_SEC = 24*60*60
def adjust_order_for(times)
to_adjust?(times) ? adjusted(times) : times
end
def to_adjust?(times)
avg_am = times.select { |t| t.am? }.avg
avg_pm = times.select { |t| t.pm? }.avg
avg_pm - avg_am >= DAY_IN_SEC/2
end
def adjusted(times)
times.map { |t|(t.am? ? t+DAY_IN_SEC : t) }
end
public
def average_time_of_day(times)
times = adjust_order_for(times.map { |t| Time.parse(t) })
Time.at(times.avg).to_s
end
Next Quiz is scheduled for 1st Nov. 2009, and will be provided by Gautam Rege.

