Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Divide the number into random number of random elements?

If I need to divide for example 7 into random number of elements of random size, how would I do this?

So that sometimes I would get [3,4], sometimes [2,3,1] and sometimes [2,2,1,1,0,1]?

I guess it's quite simple, but I can't seem to get the results. Here what I am trying to do code-wise (does not work):

def split_big_num(num):
    partition = randint(1,int(4))
    piece = randint(1,int(num))
    result = []
    for i in range(partition):
        element = num-piece
        result.append(element)
        piece = randint(0,element)
#What's next?
        if num - piece == 0:
            return result
    return result

EDIT: Each of the resulting numbers should be less than initial number and the number of zeroes should be no less than number of partitions.

like image 540
Stpn Avatar asked Apr 24 '12 20:04

Stpn


People also ask

How do you generate a random number from a list of numbers?

Note: If you want to generate random number based on a list, you can use this formula =INDEX($I$2:$I$7, RANDBETWEEN(1, 6)), and press Enter key.

How do you split a number into N parts?

Approach: There is always a way of splitting the number if X >= N. If the number is being split into exactly 'N' parts then every part will have the value X/N and the remaining X%N part can be distributed among any X%N numbers.


2 Answers

I'd go for the next:

>>> def decomposition(i):
        while i > 0:
            n = random.randint(1, i)
            yield n
            i -= n

>>> list(decomposition(7))
[2, 4, 1]
>>> list(decomposition(7))
[2, 1, 3, 1]
>>> list(decomposition(7))
[3, 1, 3]
>>> list(decomposition(7))
[6, 1]
>>> list(decomposition(7))
[5, 1, 1]

However, I am not sure if this random distribution is perfectly uniform.

like image 142
Roman Bodnarchuk Avatar answered Sep 30 '22 04:09

Roman Bodnarchuk


You have to define what you mean by "random". If you want an arbitrary integer partition, you can generate all integer partitions, and use random.choice. See python: Generating integer partitions This would give no results with 0. If you allow 0, you will have to allow results with a potentially infinite number of 0s.

Alternatively if you just want to take random chunks off, do this:

def arbitraryPartitionLessThan(n):
    """Returns an arbitrary non-random partition where no number is >=n"""
    while n>0:
        x = random.randrange(1,n) if n!=1 else 1
        yield x
        n -= x

It is slightly awkward due to the problem constraints that each number should be less than the original number; it would be more elegant if you allowed the original number. You can do randrange(n) if you want 0s but it wouldn't make sense unless there is a hidden reason you are not sharing.

edit in response to question edit: Since you desire the "the number of zeroes should be no less than number of partitions" you can arbitrarily add 0s to the end:

def potentiallyInfiniteCopies(x):
    while random.random()<0.5:
        yield x

x = list(arbitraryPartitionLessThan(n))
x += [0]*len(x) + list(potentiallyInfiniteCopies(0))

The question is quite arbitrary, and I highly recommend that you choose this instead as your answer:

def arbitraryPartition(n):
    """Returns an arbitrary non-random partition"""
    while n>0:
        x = random.randrange(1,n+1)
        yield x
        n -= x
like image 45
ninjagecko Avatar answered Sep 30 '22 04:09

ninjagecko