Skip to content

Instantly share code, notes, and snippets.

@campo
Created April 5, 2013 05:19
Show Gist options
  • Save campo/5316829 to your computer and use it in GitHub Desktop.
Save campo/5316829 to your computer and use it in GitHub Desktop.
A prototype of a solution to answer the following question on StackOverflow: http://stackoverflow.com/questions/15825827/detecting-top-movers-over-a-period-of-time
# This methodology breaks down to the following steps:
# * Determine initial times for all runners
# * Calculate average run times for all runners over the given time period (6 months)
# * Compare each runner's average performance to their initial performance
# * Sort all runners by the improvement of their average performance compared to their initial performance
# This is code I used to generate hashes of race data
#
# 6.times do
# @race_times = {}
# 50.times do
# name = "runner#{Random.rand(60)}"
# time = 120 + Random.rand(180)
# # puts "Name: #{name}, Time: #{time}"
# @race_times[name] = time
# end
# puts @race_times
# end
# You have six races worth of information. Across all races there are 60 different runners
# Each race contains a hash in which the keys are the runner name, and the values are the
# marathon time in minutes
race1 = {"runner37"=>148, "runner4"=>213, "runner27"=>147, "runner0"=>241, "runner1"=>147, "runner21"=>164, "runner32"=>245, "runner47"=>237, "runner23"=>222, "runner6"=>177, "runner25"=>214, "runner58"=>160, "runner41"=>276, "runner16"=>243, "runner59"=>213, "runner43"=>172, "runner9"=>291, "runner54"=>261, "runner36"=>225, "runner18"=>169, "runner46"=>258, "runner53"=>176, "runner52"=>285, "runner57"=>284, "runner51"=>147, "runner29"=>173, "runner12"=>122, "runner20"=>188, "runner15"=>274, "runner55"=>278, "runner45"=>260}
race2 = {"runner39"=>223, "runner20"=>213, "runner28"=>210, "runner21"=>190, "runner3"=>260, "runner7"=>246, "runner51"=>178, "runner9"=>282, "runner57"=>176, "runner31"=>298, "runner6"=>209, "runner44"=>140, "runner35"=>135, "runner16"=>206, "runner26"=>126, "runner18"=>204, "runner55"=>240, "runner46"=>137, "runner1"=>244, "runner34"=>165, "runner0"=>145, "runner40"=>263, "runner19"=>161, "runner24"=>196, "runner27"=>170, "runner12"=>187, "runner48"=>132, "runner22"=>159, "runner54"=>146, "runner38"=>225, "runner25"=>247, "runner33"=>244, "runner42"=>196, "runner47"=>180, "runner2"=>292, "runner15"=>291, "runner41"=>172, "runner23"=>201}
race3 = {"runner13"=>260, "runner18"=>120, "runner42"=>286, "runner39"=>235, "runner51"=>271, "runner40"=>179, "runner35"=>198, "runner58"=>253, "runner7"=>291, "runner50"=>136, "runner46"=>269, "runner12"=>162, "runner59"=>161, "runner9"=>148, "runner17"=>243, "runner6"=>215, "runner34"=>215, "runner14"=>221, "runner55"=>128, "runner43"=>159, "runner5"=>210, "runner22"=>218, "runner31"=>182, "runner2"=>152, "runner19"=>136, "runner16"=>253, "runner4"=>143, "runner3"=>177, "runner41"=>271, "runner44"=>214, "runner48"=>295, "runner54"=>146}
race4 = {"runner44"=>167, "runner18"=>274, "runner40"=>163, "runner29"=>157, "runner58"=>136, "runner5"=>151, "runner41"=>228, "runner6"=>206, "runner4"=>211, "runner10"=>194, "runner17"=>251, "runner11"=>203, "runner22"=>157, "runner30"=>219, "runner23"=>254, "runner20"=>215, "runner48"=>151, "runner27"=>275, "runner25"=>253, "runner56"=>169, "runner36"=>160, "runner51"=>204, "runner15"=>147, "runner43"=>182, "runner34"=>161, "runner37"=>255, "runner12"=>219, "runner33"=>185, "runner28"=>278, "runner9"=>205, "runner19"=>121, "runner2"=>202, "runner45"=>290, "runner47"=>183, "runner26"=>259}
race5 = {"runner49"=>242, "runner19"=>184, "runner38"=>135, "runner54"=>240, "runner41"=>264, "runner18"=>280, "runner20"=>199, "runner24"=>285, "runner46"=>298, "runner44"=>234, "runner28"=>182, "runner15"=>165, "runner42"=>174, "runner8"=>287, "runner3"=>198, "runner6"=>253, "runner9"=>195, "runner58"=>289, "runner12"=>181, "runner51"=>159, "runner5"=>288, "runner27"=>169, "runner13"=>210, "runner17"=>166, "runner47"=>195, "runner0"=>136, "runner23"=>204, "runner55"=>212, "runner26"=>126, "runner10"=>171, "runner50"=>170, "runner7"=>198, "runner37"=>222, "runner45"=>267}
race6 = {"runner23"=>251, "runner26"=>213, "runner2"=>199, "runner59"=>266, "runner56"=>153, "runner38"=>149, "runner45"=>245, "runner51"=>128, "runner58"=>267, "runner11"=>204, "runner28"=>199, "runner44"=>235, "runner48"=>285, "runner30"=>275, "runner7"=>226, "runner18"=>151, "runner34"=>177, "runner42"=>143, "runner15"=>123, "runner50"=>136, "runner22"=>177, "runner54"=>233, "runner36"=>260, "runner29"=>232, "runner20"=>202, "runner19"=>179, "runner17"=>146, "runner13"=>189, "runner33"=>280, "runner52"=>250, "runner21"=>153, "runner41"=>126, "runner4"=>220, "runner49"=>187, "runner55"=>189, "runner0"=>172, "runner57"=>256, "runner31"=>214, "runner35"=>120, "runner39"=>217, "runner37"=>202}
races = [race1, race2, race3, race4, race5, race6]
@initial_times = {}
@all_times = {}
@average_times = {}
# First go through all races, to find the first time we encounter for each runner
# This gives us the baseline for how a runner first performed
races.each do |race|
race.each do |runner, time|
if @initial_times[runner].nil?
@initial_times[runner] = time
@all_times[runner] = [time]
else
@all_times[runner] << time
end
end
end
puts "initial_times: #{@initial_times}"
# Now go through the race times for ever runner in all races
# We calculate each runners average completion time across all races
@all_times.each do |runner, time_array|
time_sum = time_array.inject {|sum, x| sum + x}
@average_times[runner] = time_sum * 1.0 / time_array.count
end
puts "average_times: #{@average_times}"
# Now for all runners compare their average time to their initial time
# This gives us an indication of how much they have improved since their first
# completed race.
@time_diffs = {}
@initial_times.each do |runner, time|
diff = @initial_times[runner] - @average_times[runner]
@time_diffs[runner] = diff
end
# Finally sort the hash of time_diffs and print the list of runners
# and their improvement (in minutes). This is your movers chart.
@time_diffs.sort_by {|key, value| -value}.each do |runner, improvement|
puts "Runner: #{runner}, Improvement: #{improvement}"
end
Runner: runner2, Improvement: 80.75
Runner: runner15, Improvement: 74.0
Runner: runner55, Improvement: 68.6
Runner: runner0, Improvement: 67.5
Runner: runner9, Improvement: 66.80000000000001
Runner: runner31, Improvement: 66.66666666666666
Runner: runner40, Improvement: 61.33333333333334
Runner: runner54, Improvement: 55.80000000000001
Runner: runner38, Improvement: 55.33333333333334
Runner: runner41, Improvement: 53.16666666666666
Runner: runner3, Improvement: 48.33333333333334
Runner: runner57, Improvement: 45.33333333333334
Runner: runner17, Improvement: 41.5
Runner: runner13, Improvement: 40.33333333333334
Runner: runner47, Improvement: 38.25
Runner: runner49, Improvement: 27.5
Runner: runner52, Improvement: 17.5
Runner: runner46, Improvement: 17.5
Runner: runner4, Improvement: 16.25
Runner: runner10, Improvement: 11.5
Runner: runner36, Improvement: 10.0
Runner: runner16, Improvement: 9.0
Runner: runner56, Improvement: 8.0
Runner: runner33, Improvement: 7.666666666666657
Runner: runner7, Improvement: 5.75
Runner: runner19, Improvement: 4.800000000000011
Runner: runner43, Improvement: 1.0
Runner: runner32, Improvement: 0.0
Runner: runner53, Improvement: 0.0
Runner: runner14, Improvement: 0.0
Runner: runner8, Improvement: 0.0
Runner: runner59, Improvement: -0.3333333333333428
Runner: runner11, Improvement: -0.5
Runner: runner39, Improvement: -2.0
Runner: runner42, Improvement: -3.75
Runner: runner23, Improvement: -4.400000000000006
Runner: runner21, Improvement: -5.0
Runner: runner45, Improvement: -5.5
Runner: runner5, Improvement: -6.333333333333343
Runner: runner28, Improvement: -7.25
Runner: runner50, Improvement: -11.333333333333343
Runner: runner29, Improvement: -14.333333333333343
Runner: runner34, Improvement: -14.5
Runner: runner20, Improvement: -15.400000000000006
Runner: runner35, Improvement: -16.0
Runner: runner22, Improvement: -18.75
Runner: runner25, Improvement: -24.0
Runner: runner30, Improvement: -28.0
Runner: runner18, Improvement: -30.666666666666657
Runner: runner51, Improvement: -34.16666666666666
Runner: runner6, Improvement: -35.0
Runner: runner27, Improvement: -43.25
Runner: runner24, Improvement: -44.5
Runner: runner1, Improvement: -48.5
Runner: runner12, Improvement: -52.19999999999999
Runner: runner26, Improvement: -55.0
Runner: runner44, Improvement: -58.0
Runner: runner37, Improvement: -58.75
Runner: runner58, Improvement: -61.0
Runner: runner48, Improvement: -83.75
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment