Algoritmo para encontrar o range ao qual pertence um número
Para atender uma lógica de negócio tivemos a necessidade descobrir qual range um determinado número pertencia.

Por exemplo, para intervalos de 5000, todos os números de 1 a 5000 (inclusive) pertecerão ao range 5000, os números 5001 a 10000, pertencerão ao range 10000, de 10001 a 15000, ao range de 15000 e assim por diante.
Então tínhamos que criar um algoritmo que recebendo a posição e o intervalo, devolveria o range ao qual a posição se encontrava.
def generate_range(position, interval) # Implementation end generate_range 4999, 5000 # => 5000 generate_range 5000, 5000 # => 5000 generate_range 5001, 5000 # => 10000 generate_range 12350, 5000 # => 10000
Eu dei a idéia de substrair do valor da posíção o valor do intervalo até o valor da posição ficar negativo e então multipiclar a quantidade de vezes que aconteceu a subtração pelo valor do intervalo.
A primeira versão saiu algo do tipo assim:
def generate_range(position, interval)
rest = position - interval
substract = 1
if rest > 0
substract += 1
while rest > 0
rest = rest - interval
substract += 1 if rest > 0
end
end
substract * interval
end
Zuado esse código, né?
Nisso o Herbert Francarelli perguntou para o Fábio Akita se havia alguma forma em Ruby para diminuir a quantidade de código desse método. De bate pronto ele pensou em usar o método include? da classe Range, mas queria uma solução de uma linha.
Ficamos de cada um da equipe tentar encontrar a solução do problema no fim de semana.
Eu comecei tentando utilizar o método include? da classe Range:
def generate_range(position, interval)
lrange = 1
rrange = interval
while !(lrange..rrange).include?(position) do
lrange += interval
rrange += interval
end
rrange
end
E também consegui resultado semelhante com a ajuda do método between? da módulo Comparable:
def generate_range(position, interval)
lrange = 1
rrange = interval
while !position.between?(lrange, rrange) do
lrange += interval
rrange += interval
end
rrange
end
Mas somente quando eu parei de procurar alguma solução com comandos Ruby e pensei em solução matemática, encontrei o que eu queria:
def generate_range(position, interval) ((position - 1) / interval + 1) * interval end
O Fábio Akita já tinha criado o método com uma linha no mesmo dia. Ele combinou a solução matemática com recursos da linguagem:
def generate_range(position, interval) (position.to_f / interval.to_f).ceil * interval end
Essas coisas (entre muitas outras) é que tornam divertido o trabalho de desenvolvedores de software.


Comentários