0

I am trying to convert an integer (num) to bins as per given interval. the bin size (intervals) are [1, 200), [200, 400), [400, 800), [800, 1200), [1200, num]

I'am doing it in a crude way ...

def create_bins(num):
    """Create Bins as per given intervals."""
    s1, s2, s3, s4 = 199, 200, 400, 400
    if num > 1200:
        res = [s1, s2, s3, s4, num - (s1 + s2 + s3 + s4)]
    elif num < 1200 and num >= 800:
        res = [s1, s2, s3, num - (s1 + s2 + s3)]
    elif num < 800 and num >= 400:
        res = [s1, s2, num - (s1 + s2)]
    elif num < 400 and num >= 200:
        res = [s1, num - s1]
    else:
        res = [num]

    return res

this function for create_bins(1041) returns [199, 200, 400, 242] which is correct. However, I'am sure there are better ways to get it done...

Will appreciate if you can lead me towards better solutions for these kind of problem.

Arun Kumar Khattri
  • 1,519
  • 15
  • 25

2 Answers2

1

this may be good idea.

  def create_bins_new(num):
        val = [199,200,400,400]
        out = []
        for v in val:
            if v < num:
                out.append(v)
                num -= v
        out.append(num)
        return out
0

In case of a very large number of bins, compute the prefix sum of the bin sizes, locate num in this list by binary search and assemble the result.

import bisect

# Data arrays
bins= [199, 200, 400, 400]
prefix= [sum(bins[:i]) for i in range(len(bins)+1)]

# Try various values
for num in [1, 150, 199, 200, 201, 798, 799, 800, 801, 1041, 2000]:
    # Search and concatenete
    index= bisect.bisect_left(prefix, num) - 1
    print(num, bins[:index] + [num - prefix[index]])

Output:

1 [1]
150 [150]
199 [199]
200 [199, 1]
201 [199, 2]
798 [199, 200, 399]
799 [199, 200, 400]
800 [199, 200, 400, 1]
801 [199, 200, 400, 2]
1041 [199, 200, 400, 242]
2000 [199, 200, 400, 400, 801]
Yves Daoust
  • 672
  • 9