Skip to content

@TomV /tomv.rb secret

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
refactored based on challenge feedback (unit test, inject, and strfmtime)
# 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
Something went wrong with that request. Please try again.