views:

141

answers:

3

I need to create one array of numbers inside one range, like:

[1..5] in 10 times = [1,1,2,2,3,3,4,4,5,5]

[1..5] in 5 times = [1,2,3,4,5]

[1..5] in 3 times = [1,3,5]

def distribute(start_value, end_value, times, is_integer)
    array = Array.new(times-1)

    min_value = [end_value,start_value].min
    max_value = [end_value,start_value].max

    if max_value-min_value<times
      factor = (max_value-min_value).abs/(array.size).to_f
    else
      factor = (max_value-min_value).abs/(array.size-1).to_f
    end

    for i in 0..array.size
      v = [ [max_value, factor*(i+1)].min, min_value].max
      is_integer ? array[i] = v.round : array[i] = v
    end

    start_value < end_value ? array : array.reverse
  end

distribute(1, 5, 10, true) => [1, 1, 1, 2, 2, 3, 3, 4, 4, 4] #WRONG should be [1,1,2,2,3,3,4,4,5,5]

distribute(5, 1, 5, true) => [5, 4, 3, 2, 1] #OK

distribute(1, 5, 3, true) => [4, 5, 5] #WRONG should be [1, 3, 5]

+5  A: 

How 'bout this:

def distribute(min,max,items)
  min,max = [min,max].sort
  (0...items).map {|i| (min + i * (max - min) / (items-1.0)).round}
end

Or if you really need the int/float flag:

def distribute(min,max,items,ints)
  min,max = [min,max].sort
  a = (0...items).map {|i| min + i * (max - min) / (items-1.0)}
  ints ? a.map {|i| i.round} : a
end

And if you really need this to go in reverse if the parameters are given to you backwards:

def distribute(min,max,items,ints)
  usemin,usemax = [min,max].sort
  diff = usemax - usemin
  a = (0...items).map {|i| usemin + i * diff / (items-1.0)}
  a.map! {|i| i.round} if ints
  min != usemin ? a.reverse : a
end
glenn mcdonald
And obviously you can leave out the min,max= part if you know you're getting the parameters in the right order...
glenn mcdonald
Maybe I'm misunderstanding the problem, but this answer doesn't seem to work correctly for the OP's second use case: `distribute(5, 1, 5, true) => [5, 4, 3, 2, 1]`.
FM
True. I just added another variation with that case.
glenn mcdonald
A: 

it's work's...

thank you glenn mcdonald and FM.

Alexandre Bini
what you realy wanted to do, was writing a comment on an answer, not an own answer to your question
johannes
sorry... itś was my first question
Alexandre Bini
A: 

just a little correction... when the array_size is 0

  def distribute(start_value, end_value, array_size, want_ints)
    diff = 1.0 * (end_value - start_value)
    n = [array_size-1, 1].max

    (0..(array_size-1)).map { |i|
        v = start_value + i * diff / n
        want_ints ? v.round : v
    }    
  end
Alexandre Bini
Rather than complicate the algorithm for the special case, you could short-circuit the method: `return [] unless array_size > 0`. At least for me, it's easier to understand the code that way.
FM