In Ruby, I want to group an array of integers by a running total without the total going over a certain number. While keeping the integers in order.
I have this array of numbers from zero to one hundred, inclusive:
numbers = [20, 40, 90, 20, 0, 10, 5, 30, 100, 40, 30]
I want to group them into sub-arrays so that the total within a sub-array never exceeds 100.
For example, the first two numbers 20 and 40 sum to 60. The next number, 90, would cause the running total to be higher than 100. Therefore [20, 40]
will form one sub-array and [90]
will form the next sub-array. Both sub-arrays are less than (or equal to) 100. The numbers are kept in order. It's not permissible to grab the number 90 and move it next to the number 10 to make an even group of 100, because those numbers are not adjacent in the input array.
Thus the output should look like this:
numbers_in_groups_of_less_than_100 = [
[20, 40],
[90],
[20, 0, 10, 5, 30],
[100],
[40, 30]
]
I wonder if this is possible with Ruby's inject
method, but I haven't figured out the right block to pass to it. Also, it seems to me that a while
loop could be used to accomplish this, but I'm having trouble figuring out the specifics of how to trigger the breakup of the array and reset the counter.
You could use slice_before
along with a running total that you update yourself:
numbers = [20, 40, 90, 20, 0, 10, 5, 30, 100, 40, 30]
total = 0
slices = numbers.slice_before do |i|
if total + i > 100
total = i
true
else
total += i
false
end
end
slices.to_a
#=> [[20, 40], [90], [20, 0, 10, 5, 30], [100], [40, 30]]