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.