Instantly share code, notes, and snippets.

# mwlang/michaellang.rbSecret Created Oct 10, 2009

What would you like to do?
 # Given a series of times, computes the average time for the series, returning the # calculated average time as a string. # # >> average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"]) # => "12:01am" # # >> average_time_of_day(["6:41am", "6:51am", "7:01am"]) # => "6:51am" require 'time' DEGREES_IN_CIRCLE = 360.0 TWENTY_FOUR_HOUR_MINUTES = 24 * 60 DEGREES_PER_MINUTE = DEGREES_IN_CIRCLE / TWENTY_FOUR_HOUR_MINUTES class Time # Treats hours and minutes as "one hand" on a analog clock for 1440 minute clockface def degrees (self.hour * 60 + self.min) * DEGREES_PER_MINUTE end # converts degrees to radians def radians self.degrees * Math::PI / 180 end # computes point on circumference of the imaginary 1440 minute clockface def point [Math::sin(self.radians), Math::cos(self.radians)] end # given a point on the imaginary 1440 minute clockface, returns time object # corresponding to that point. def self.at_point(point) degrees = Math::atan2(point[0], point[1]) * 180 / Math::PI hr = (degrees / DEGREES_PER_MINUTE / 60).to_i m = (degrees / DEGREES_PER_MINUTE).round - hr * 60 parse("#{hr}:#{m}") end end def average_time_of_day(times) # parse the given time strings into Time objects real_times = times.map{|m| Time.parse(m)} # sum up and then take average of the points in the time series sum_pt = real_times.inject([0, 0]) do |pt, t| pt[0] += t.point[0] pt[1] += t.point[1] pt end avg_pt = [sum_pt[0] / times.size, sum_pt[1] / times.size] # translate the computed average back into time object and print Time.at_point(avg_pt).strftime("%I:%M%p").downcase end