Instantly share code, notes, and snippets.

# TomV/tomv.rbSecret Created Oct 9, 2009

What would you like to do?
refactored based on challenge feedback (unit test, inject, and strfmtime)
 # Ruby Programming Challenge For Newbies, (#2) # Author: tomv # (refactored after close of challenge to incorporate feedback: 1.) use inject and 2.) use Test::Unit # # Calculate the average time of day from several times in the format # [ '12:11am', '11:51pm','11:56pm','12:01am', '12:06am'] # returns the average time in string format # => '12:01am' # My approach was to get the average difference between each of the # times, compared to the first time in the list. # Then add the average difference in time to the base time to get an average. # The trick was to figure out how to minimize the differences by moving the day around # since for the edge cases, the next day (12:01 pm) or the previous day (11:55am) # might yeild a smaller difference that the same time on the same day. # Would be easy to extend this to get a standard deviation of the time differences, so you could # Likely arrival is "12:30pm +/- 12 minutes in most cases, or something. # # I included a simple set of tests as an additional function: test_average_time_of_day() # that runs through a few test cases. # Note that the results for average_time_of_day(['12am', '12pm']) could be either '6pm' or '6am' require 'time' ONE_DAY = 86400 # day in seconds # To run in irb # >load 'tomv.rb' # >average_time_of_day([ '12:11am', '11:51pm','11:56pm','12:01am', '12:06am']) # => "12:01am" def average_time_of_day(times) base_time = Time.parse(times[0]) #take the first time, and use as a 'base' then calculate avg. difference. sum_of_time_differences = times.inject(0.0) do |sum,t| given_time = Time.parse(t) # Time.parse assumes current day when parsing if (base_time.hour > 12) # Alternative time is prev day for am or next day for pm alternative_time = given_time + ONE_DAY else alternative_time = given_time - ONE_DAY end diff1 = given_time - base_time diff2 = alternative_time - base_time sum + ((diff1.abs < diff2.abs)? diff1 : diff2) end average_difference = sum_of_time_differences/times.size average_time = base_time + average_difference average_time.strftime('%l:%M%p').downcase.strip end ################################################################################### # TEST CASES ################################################################################### require 'test/unit' class ChallengeTest < Test::Unit::TestCase def test_initial_challenge_example_1 assert_equal("12:01am", average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"])) end def test_example_2 assert_equal("6:51am", average_time_of_day(["6:41am", "6:51am", "7:01am"])) end def test_edge_case_noon_and_midnight assert_equal("6:00pm", average_time_of_day(['12am','12pm'])) end def test_around_midnight_example assert_equal("12:01am", average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"])) end end