-
-
Save RLGGHC/4f6807eef49064027a3c to your computer and use it in GitHub Desktop.
Chris Strom Solution
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
=begin | |
My solution includes comments to aid in understanding, but I should probably add an overall approach description as well. | |
The problem is solvable without geometry, but not quite as generalizable. Regardless, some extension to the Float and String class will be needed (to convert back and forth between time strings and floats for averaging). | |
== Expected output | |
list = %w{23:15 00:03 23:30 23:23 23:48} | |
average_time_of_day(list) | |
=> "23:35" | |
list = %w{06:15 07:03 06:30 06:23 06:48} | |
average_time_of_day(list) | |
=> "06:35" | |
== Hints | |
Your digital ways will not help you, time of day is cyclical. | |
== Note | |
There is a newsgroup that actually discusses this problem and offers some solutions that are very close to being complete. I'd rather not give folks hints that point them to that discussion. Like I said, it is possible to come up with a close approximation of the solution without geometry. Besides, I am somewhat hopeful that someone can surprise me by coming up with an elegant solution without geometry :) | |
=end | |
class Float | |
def to_time_string | |
hours = self.to_i | |
"%02d:%02d" % [hours, (self-hours)*60] | |
end | |
end | |
class String | |
# Given a time string (e.g. "23:15"), return a numeric | |
# representation (e.g. 23.25) | |
def to_time_float | |
hours, minutes = self.split(":") | |
(hours.to_i + minutes.to_f/60) | |
end | |
end | |
class GeometricTime | |
# Given a list of 24-hour times (e.g. ["23:50", "00:00", "00:00"]), | |
# returns the average (e.g. "00:00") | |
def self.average(list) | |
vector_sum = list.inject([0,0]) do |memo, time| | |
x, y = x_y_from_time(time) | |
[memo[0] + x, memo[1] + y] | |
end | |
time_from_x_y(*vector_sum) | |
end | |
# Convert time on a 24 hour analog clock to x-y coordinates. Align | |
# midnight with the x axis for easier conversion. | |
# * midnight => [1, 0] | |
# * "06:00" => [0, -1] | |
# * "12:00" => [-1, 0] | |
# * "18:00" => [0, 1] | |
def self.x_y_from_time(time) | |
# negative because angles increase counter-clockwise | |
radians = - 2 * Math::PI * time.to_time_float / 24 | |
[Math.cos(radians), Math.sin(radians)] | |
end | |
# Convert from x-y coordinates back to a time string (e.g. [1, 0] => | |
# "00:00" | |
def self.time_from_x_y(x, y) | |
atan2 = Math.atan2(y, x) | |
angle = atan2 < 0 ? atan2 + 2*Math::PI : atan2 | |
time = ((2 * Math::PI - angle) / (2*Math::PI)) * 24 | |
time.to_time_string | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment