Created
October 8, 2009 21:11
-
-
Save asmodis/205429 to your computer and use it in GitHub Desktop.
Solution for RPCFN #2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "time" | |
module AverageTimeCalculator | |
SecondsPerDay = 86400 | |
Noon = 12 | |
#Calculates the average of the given times. | |
#Parameter times is supposed to be an array of strings, each string with format HH:MM(am|pm) | |
# | |
#*Examples*: | |
# average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"]) # => "12:01am" | |
# average_time_of_day(["11:51am", "11:56am", "12:01pm", "12:06pm", "12:11pm"]) # => "12:01pm" | |
# | |
#-- | |
#Strategy: | |
# Case1: All times are am (or all times are pm) | |
# => simply calculate the average | |
# Case2: Times are mixed | |
# => Calculate average assuming all times are from a single day | |
# Calculate average assuming all am times are from the following day | |
# Choose average suiting the given times best depending on a simple metric | |
# | |
#The code is not suited for calculating the average delay of a flight, because it | |
#doesn't differentiate between different days. So a flight sheduled at 10pm arriving 23h late | |
#will be treated as a flight arriving one hour earlier. | |
# | |
#Other thingy: Whats the average of 12:00am and 12:00pm? | |
# I decided to choose the earlier time (in this case 6am) | |
#++ | |
def average_time_of_day(times_array) | |
#Fix a time for the (very very unlikly) case, that parsing skips midnight | |
now = Time.now | |
am_times, pm_times = | |
times_array.map { |time_str| Time.parse(time_str, now) }.partition { |time| time.hour < Noon} | |
shifted_am_times = [] | |
unless am_times.empty? or pm_times.empty? | |
shifted_am_times = am_times.map { |time| time + SecondsPerDay } | |
end | |
best_average(am_times + pm_times, pm_times + shifted_am_times).strftime("%I:%M%p").downcase | |
end | |
private | |
def best_average(timeset1, timeset2) | |
if timeset2.size < timeset1.size #shifting wasn't needed | |
average(timeset1) | |
else | |
choose_best_average timeset1, timeset2 | |
end | |
end | |
def choose_best_average(tset1, tset2) | |
av1, av2 = average(tset1), average(tset2) | |
difference(av1, tset1) <= difference(av2, tset2) ? av1 : av2 | |
end | |
def average(times) | |
total = times.inject(0) do |sum, time| | |
sum + time.to_i | |
end | |
Time.at(total / times.size) | |
end | |
def difference(time0, times) | |
times.inject(0) { |res,time| res + (time - time0).abs } | |
end | |
end | |
include AverageTimeCalculator | |
puts average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"]) | |
puts average_time_of_day(["11:51am", "11:56am", "12:01pm", "12:06pm", "12:11pm"]) | |
puts average_time_of_day(["6:41am", "6:51am", "7:01am"]) | |
puts average_time_of_day(["12:00pm", "12:00am"]) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment