Created
April 5, 2013 05:19
-
-
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 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
# 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