Divide a number in arbitrary sizes in Python
I have x = 10
and y = 100
.
Can I distribute elements y
in arbitrary sized chunks among x
'element holders ??
I want to create categories x
, each with a random number of items; however, the number of items created must be accurate y
.
I think something like
# number of categories and items
x = 10, y = 100
# keep track of how many items we have left to add
y_left = y
# create all categories
for i in range(x):
# create category
# find number of items in this category
num_items_in_category = random.randint(1, y_left)
# create items
for j in range(num_items_in_category):
# create item
# set new number of items left to add
y_left -= num_items_in_category
source to share
Using the functions from this answer , you can generate a list of x random numbers that sum to y.
Iterate through the elements of this list and make as many random selections (deleting) from the collection of elements for each holder.
Or for example:
# requires RandIntVec() & RandFloats() from linked answer
# whatever population you are choosing from, example letter
population = list('qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890')
# sizes (whatever you want)
num_of_holders = 7
total_elements = len(population)
# empty holder to put results in
element_holder = [[] for _ in xrange(num_of_holders)]
# distribute total_elements elements in randomly-sized portions among num_of_holders 'element holders'
random_portions_in_holder = RandIntVec(num_of_holders, total_elements, Distribution=RandFloats(num_of_holders))
# assign each portion of elements to each 'holder'
for h, portion in enumerate(random_portions_in_holder):
for p in range(portion):
index = random.randrange( len(population) )
element_holder[h].append(population.pop(index))
# display
print 'Randomly-portioned elements'
for h in element_holder:
print h
# verify
print '\nMatch desired result?'
print 'total_elements :', total_elements
print 'elements in holders :', sum([len(h) for h in element_holder])
print 'match :', total_elements == sum([len(h) for h in element_holder])
Output
Randomly-portioned elements
['M', 'N', 'f', 'V', 'v', 'h', 'i', 'H', '6', '5', 'j', '7', 'r']
['u', 'Z', 'C', 'I', 's', 'm', 'g', 'p', 'q', 'a', 'O', 'T', 'L']
['K', 'E', 'P', 'U']
['Y', 'D', 'A', 'l', 'J', 'R', 'b', 'c', 'z', 'F']
['0', '1', 'o', 'X', 'G', '4', 'W', '3', '2']
['d', 'Q']
['e', 'y', 'B', '8', 'x', 'k', 'w', 't', 'S', 'n', '9']
Match desired result?
total_elements : 62
elements in holders : 62
match : True
PS I had some indentation errors when I copied related functions, you may need to fix them. The pod code elif Distribution.lower() == 'normal':
must be at level un given level 1. I posted an edited version (end of approval), so depending on when you copy you may or may not need to edit.
source to share
It's not too difficult. Let's create our containers:
import random
num_containers = 10
num_objects = 100
containers = [[] for _ in range(num_containers)]
objects = (some_object() for _ in range(num_objects))
# we don't need a list of these, just have to iterate over it, so this is a genexp
for object in objects:
random.choice(containers).append(object)
source to share
I faced a similar problem in my work and solved the problem using a dictionary.
import random
# number of categories (number of keys in the dictionary) and items (sum of all the value)
x, y = 10, 100
snpDict = {}
i = 0
while i < y:
a = random.randint(0, x)
if a in snpDict:
snpDict[a] += 1
else:
snpDict[a] = 1
i += 1
I have a huge number of categories and items, the performance is not very good.
source to share