Instantly share code, notes, and snippets.

# timrandg/timRand.rbSecret Created Oct 11, 2009

 =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"