Quick solution to #118

From: "Paul M. Lambert" <plambert@plambert.net>
Date: March 30, 2007 2:10:12 PM CDT
To: submission@rubyquiz.com
Subject: Quick solution to #118

Just threw this together, and now I'm out of time…

It implements (badly) the basic requirement, as well as an optional tolerance (for +/- N seconds).

Naturally, there are no comments. But it seems to work. Yeah, not exactly a stellar example. I have lots left to learn, for sure! :slight_smile:

I look forward to seeing others' solutions!

Paul M. Lambert

#!/opt/local/bin/ruby -w

# ruby quiz #118

$calculated_distance_for_number=Hash.new

class Integer
  def reversed_digits
    self.to_s.split('').reverse
  end
end

def position(digit)
  if digit.nil? or digit.to_i == 10
    return 1,3
  elsif digit.to_i == 0
    return 0,3
  else
    return ((digit.to_i - 1) % 3), ((digit.to_i - 1) / 3)
  end
end

def distance_between_digits(a,b)
  x1, y1 = position(a)
  x2, y2 = position(b)
  x = (x1 - x2).abs
  y = (y1 - y2).abs
  return (x*x + y*y)
end

def distance_for_number(num)
  num = num.to_i
  if $calculated_distance_for_number[num]
    return $calculated_distance_for_number[num]
  end
  d = num.to_i.reversed_digits
  total_distance = 0

  last_digit=nil
  while d.size > 0
    next_digit = d.shift
    total_distance += distance_between_digits(last_digit, next_digit)
    last_digit = next_digit
  end
  $calculated_distance_for_number[num] = total_distance
end

def all_representations_of(s)
  representations = Array.new
  mins = (s.to_i / 60)
  secs = s.to_i - 60*mins
  if mins == 0
    [ secs ]
  elsif secs > 39
    [ 100*mins+secs ]
  else
    [ 100*mins+secs, 100*(mins-1)+secs+60 ]
  end
end

def best_input_for(seconds, tolerance=0)
  tolerance=tolerance.to_i
  seconds=seconds.to_i
  range_min=[seconds-tolerance, 0].max
  range_max=seconds+tolerance
  representations = Array.new
  (range_min .. range_max).each do |s|
    representations.concat(all_representations_of(s))
  end
  representations.sort { |a,b| distance_for_number(a) <=> distance_for_number(b) }[0]
end

[99, 71, 120, 123].each do |s|
  puts "#{s}: #{best_input_for(s)}"
end

···

Begin forwarded message: