Skip to content

Instantly share code, notes, and snippets.

@TomV

TomV/tomv.rb Secret

Created October 9, 2009 22:48
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 TomV/6da8bd7345d7ed7a6040 to your computer and use it in GitHub Desktop.
Save TomV/6da8bd7345d7ed7a6040 to your computer and use it in GitHub Desktop.
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment