Following is my (very late, but short) submission. I first attempted to be really tricky about the time distribution in a variety of ways (which I'll mention in the Summary), but found that the following code gave pretty good results (which you'll see in the upcoming results email). class Time def round_to( seconds ) seconds = seconds.round Time.at( self.to_i / seconds * seconds ) end end class FuzzyTime FIVE_MINS = 5 * 60 TEN_MINS = 10 * 60 attr_reader :actual def initialize( start_time=Time.new ) @last_fuzzy = @actual = @fuzzy = start_time end def update now = Time.new elapsed = now - ( @last_update || now ) advance( elapsed ) @last_update = now end def advance( seconds_forward ) @actual += seconds_forward # Randomly move forward, centered around the desired seconds @fuzzy += seconds_forward * 2 if rand < 0.5 # Ensure the fuzzy time is within legal bounds overshoot = @fuzzy - @actual if overshoot > FIVE_MINS @fuzzy = @actual + FIVE_MINS elsif overshoot < -FIVE_MINS @fuzzy = @actual - FIVE_MINS end # Ensure that the fuzzy time is not less than the last *displayed* if @fuzzy.round_to( TEN_MINS ) < @last_fuzzy.round_to( TEN_MINS ) if $DEBUG puts "It is #{@actual.short}; " + "I wanted to show #{@fuzzy.short} (#{@fuzzy.to_fuzzy})," + " but I last showed " + "#{@last_fuzzy.short} (#{@last_fuzzy.to_fuzzy})" end @fuzzy = @last_fuzzy end end def to_s # only record the last *displayed* time, to allow backtracking # as often as possible @last_fuzzy = @fuzzy s = @fuzzy.strftime("%H:%M") s[4] = "~" s end end