Página Inicial > Ruby > Algoritmo para encontrar o range ao qual pertence um número

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.


Ruby , ,

  1. Nenhum comentário ainda.
  1. Nenhum trackback ainda.