Skip to content

Instantly share code, notes, and snippets.

@timrandg
Created October 11, 2009 03:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timrandg/7e4dd13fbba60b7d0b39 to your computer and use it in GitHub Desktop.
Save timrandg/7e4dd13fbba60b7d0b39 to your computer and use it in GitHub Desktop.
=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