secret
Last active

refactored based on challenge feedback (unit test, inject, and strfmtime)

  • Download Gist
tomv.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
# 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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.