-
-
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 | |
# | |
# 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' | |
# 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) | |
total = 0.0 | |
base_time = Time.parse(times[0]) #take the first time, and use as a 'base' then calculate avg. difference. | |
times.each do |t| | |
simple_time = Time.parse(t) # Time.parse assumes current day when parsing | |
d1 = base_time - simple_time # Get the time difference between base and current item's time for same day | |
prev_next = (base_time.hour > 12)? 1:-1 # Get diff between base and next or prev day.(next day for pm, prev day for am times) | |
d2 = base_time - (simple_time + 86400*prev_next) # use next day time | |
diff = (d1.abs < d2.abs)? d1: d2 # select the smallest difference | |
total += diff # running total of differences used for calc. avg. difference from base. | |
end | |
# calcuate average time by adding avg. difference of times to the base time, then format | |
(base_time - (total/times.size)).strftime('%l:%M%P') | |
end | |
# Simple test of function | |
# Run the function through it's paces with a few simple tests | |
def test_average_time_of_day | |
test=[] | |
test[0] = { | |
:description => 'Initial Challenge Example', | |
:input_times => [ '12:11am', '11:51pm','11:56pm','12:01am', '12:06am'], | |
:correct_answer => '12:01am' | |
} | |
test[1] = { | |
:description => 'Additional provided example', | |
:input_times => ['6:41am','6:51am','7:01am'], | |
:correct_answer => '6:51am' | |
} | |
test[2] = { | |
:description => 'Edge case: 12am and 12pm (6am or 6pm are correct)', | |
:input_times => ['12am','12pm'], | |
:correct_answer => '6:00pm' | |
} | |
test[3] = { | |
:description => 'Edge case: times around noon time ( AM to PM)', | |
:input_times => ['11:45am','12:15pm','11:50am', '12:10pm' ], | |
:correct_answer => '12:00pm' | |
} | |
test[4] = { | |
:description => 'Simple case with several entries', | |
:input_times => ['7:15am','7:30am', '7:45am', '7:30am', '7:30am', '7:45am','7:15am'], | |
:correct_answer => '7:30am' | |
} | |
test.each do |item| | |
puts "Test: #{item[:description]} " | |
puts "Input times: #{item[:input_times].inspect}" | |
puts "Expected: #{item[:correct_answer]}" | |
puts "Got: #{average_time_of_day(item[:input_times])}" | |
success = average_time_of_day(item[:input_times]).strip == item[:correct_answer].strip | |
if success | |
puts '=========== PASSED ==============' | |
else | |
puts '########### FAILED ##############' | |
end | |
puts '---------------------------------------------' | |
end | |
puts "All Done" | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment