-
-
Save timrandg/7e4dd13fbba60b7d0b39 to your computer and use it in GitHub Desktop.
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 | |
Name: Tim Rand | |
Occupation: Stem cell research, medicine | |
email: timrandg@gmail.com | |
country of residence: USA | |
code compatibility: 1.9 works, 1.8 not checked. | |
This was a fun quiz. I solved it by converting all the strings to time objects and then | |
convert those objects to times to minutes from midnight. However, you cannot just average | |
the minutes because of cases | |
that span midnight (11:59pm and 12:01am => (1439 + 1)/2). So, I converted all times to a | |
vector (direction and distance) from midnight. This allows proper averaging as the previous | |
case is now (-1+1)/2. Then the averaged number needs to be converted back into a time object | |
and then printed out in the proper format. Several test cases and the results are at the bottom. | |
The syntax of the method call and output are as required by the quiz description. Comments | |
are included in the code below. | |
=end | |
require 'time' | |
require 'mathn' | |
#takes an array of times as strings and finds the average time of the event | |
def average_time_of_day(array_of_str) | |
#get Time objects of all strings | |
array_of_str.collect!{|str_time| Time.parse(str_time)} | |
#get total minutes of each time | |
in_minutes = array_of_str.collect{|time| ((time.strftime('%H').to_i * 60 + time.strftime('%M').to_i))} | |
#get distance from midnight (negative number for before midnight, positive if after midnight) | |
from_midnight = in_minutes.collect{|time| dist_from_midnight(time)} | |
#sum the distances from midnight | |
total_minutes = sum(from_midnight) | |
#average of distances from midnight | |
average_minutes = total_minutes/from_midnight.length | |
#convert average distance from midnight back into a Time.parse-able string | |
t = o_clock(average_minutes) | |
#parse into time object | |
parsed = Time.parse(t) | |
#format output | |
format(parsed) | |
end | |
#sums an array | |
def sum(arr) | |
arr.inject{|sum, n| sum+n} | |
end | |
#takes a num in minutes and converts it to hours:minutes | |
def o_clock(num) | |
hours = (num/60).to_f | |
minutes = (num%60).to_f | |
sprintf "%d:%d" %[hours, minutes] | |
end | |
#finds direction and distance in minutes of shortest length from midnight (1440 minutes), these vectors can be added toward finding the average | |
def dist_from_midnight(num) | |
arr = [num-1440,num%1440].sort!{|a,b| a.abs <=> b.abs}.first | |
end | |
#converts a time object to the format described in the examples | |
def format(time) | |
t = time.strftime('%I:%M%p').downcase | |
#remove leading zero if present. Scan kindly returns the whole string if no match is found. | |
t.scan(/[^0].*/).first | |
end | |
#test cases | |
ave = ["11:41pm", "10:51am", "7:01am"] | |
ave1 = ["6:41am", "6:51am", "7:01am", "9:09pm"] | |
ave2 = ["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"] | |
ave3 = ["12:00pm"] | |
ave4 = ["12:04am", "11:52pm","12:01am", "11:57pm"] | |
#results | |
t = average_time_of_day(ave) # => "5:51am" | |
t = average_time_of_day(ave1) # => "4:25am" | |
t = average_time_of_day(ave2) # => "12:01am" | |
t = average_time_of_day(ave3) # => "12:00pm" | |
t = average_time_of_day(ave4) # => "12:58am" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment