-
-
Save TomV/6da8bd7345d7ed7a6040 to your computer and use it in GitHub Desktop.
refactored based on challenge feedback (unit test, inject, and strfmtime)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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