```# My straight-forward solution.

require 'enumerator'

# How much can the time differ?
FUZZ = 0

POS = { ?1 => [0,0], ?2 => [1,0], ?3 => [2,0],
?4 => [0,1], ?5 => [1,1], ?6 => [2,1],
?7 => [0,2], ?8 => [1,2], ?9 => [2,2],
?0 => [1,3], ?* => [2,3] }

def metric(string)
string.enum_for(:each_byte).map { |b| POS[b] }.
enum_for(:each_cons, 2).inject(0) { |sum, ((x1,y1), (x2, y2))|
# 1-norm
# sum + (x1-x2).abs + (y1-y2).abs

# 2-norm
sum + Math.sqrt((x1-x2)**2 + (y1-y2)**2)
}
end

def entries(time)
return []  if time <= 0

min, sec = time.divmod(60)
entries = []

# seconds only
entries << "%d*" % [time]                 if time < 100

# usual time format
entries << "%d%02d*" % [min, sec]

# more than 60 seconds
entries << ("%d%02d*" % [min-1, sec+60])  if min > 1 && sec < 40

entries
end

1.upto(999) { |time|
entries = (-FUZZ..FUZZ).map { |offset| entries(time + offset) }.flatten

# Sort by movement length, then by keypresses.
quickest = entries.sort_by { |s| [metric(s), s.size] }.first
puts "%3d (%02d:%02d): %s" % [time, time.divmod(60), quickest].flatten
}

__END__
--
Christian Neukirchen  <chneukirchen / gmail.com>  http://chneukirchen.org

```