I’m Dangerous with Ruby!

My solution was selected as the winning solution for RubyLearning.com’s RPCFN #2 “Average Arrival Time for A Flight.”

This challenge involved averaging times of the day without the actual day in the context.  When I first started to tackle the problem I thought to myself that this will be very easy.  Then I hit the “no day” context and realized that this problem was much tougher than I anticipated.  When I finally saw the posted solutions including Chris Strom’s (blog) it was like decades old high school math came rushing back to me.  I would have never thought of plotting points on a graph but now that I’ve been exposed I’m certain I will never forget it!

My friend [and commuting body] Matt and I talked through the problem during our drive home as we sat in Virginia I-495 outer loop and I-95S traffic.  He had some ideas about plotting the problem linearly around 0 but ultimately I ended up going with making assumptions about how close the provided times were to midday and midnight.

require 'time'

SECONDS_IN_DAY = 86400
MIDNIGHT = Time.parse("12:00AM").to_i
MIDDAY = Time.parse("12:00PM").to_i

def average_time_of_day(times)
  seconds = []
  times.each {|time| seconds << Time.parse(time).to_i}
  seconds.sort!
  if (seconds.first - MIDNIGHT) < (seconds.last - MIDDAY)
    seconds.map! {|s| s < MIDDAY ? s += SECONDS_IN_DAY : s }
  end
  Time.at(seconds.inject { |sum,n| sum += n }.to_f / seconds.length).strftime("%I:%M%p").downcase
end

 

Gist: https://gist.github.com/5b371226faf83af50d7e

Interview: http://rubylearning.com/blog/2009/10/22/charles-feduke-winner-rpcfn-2/


  • Pickle Pumpers

    Hmm. Seems like you're doing an awful lot of work that's not needed. Maybe I missed something.

    Here's my solution:

    #!/usr/bin/env ruby
    require 'time'

    def average_time_of_day(times)
    @total_time = 0
    times.each do |time|
    @total_time += Time.parse(time, Time.at(0)).to_i
    end
    puts “Average time: #{Time.at(@total_time / times.length).strftime(”%I:%M%p”).downcase}”
    end

    average_time_of_day(ARGV)

  • Pickle Pumpers

    Oh, I see. They assumed if you have times like 11:30pm and 12:15am the am time would be after the pm time. Except what if it isn't. The question itself is flawed. Congratz though on your win.

  • Pickle Pumpers

    I fixed my code to allow for the poorly designed challenge… I thought it was too easy:

    #!/usr/bin/env rubyrequire 'time'
    
    def average_time_of_day(times)  times.sort!  @total_time = 0   times.each_with_index do |str_time,index|    time = Time.parse(str_time, Time.at(0)).to_i    time += 86400 if time + 43200 < (@total_time / (index + 1))    @total_time += time  end  puts "Average time: #{Time.at(@total_time/times.length).strftime("%I:%M%P")}"end
    
    average_time_of_day(ARGV)