Improve this recursive code please!

Anton Vredegoor anton at vredegoor.doge.nl
Wed May 7 04:52:23 EDT 2003


#! /usr/bin/env python

"""
Function bins returns a list with all possible ways of distributing
m bricks into n bins. The partition code is based on pseudo code
from Kreher and Stinson.
"""

def starters(L):
    #helper function for anagram, returns a list of 2-tuples
    n,np,R = len(L),1,range(len(L))
    bf = [L[:i].count(L[i]) for i in R]
    for i in R: np = np*(n-i)/(bf[i]+1)
    return [(i,np*L[i:].count(L[i])/n) for i in R if not bf[i]]
    
def anagram(L,index=0):
    #return an anagram of list L
    remain, res, T = index, [], L[:]
    while T:
        for j,k in starters(T):
            if remain-k < 0:
                res.append(T.pop(j))
                break
            remain -= k
    return res

def nperm(L):
    #return the number of possible anagrams of list L
    return reduce(lambda a,b:a+b,[k for j,k in starters(L)])

class Partition:
    #helper class for partition information

    def __init__(self,m):
        self.m = m
        self.parts = [0]*(m+1)

    def  dump(self,numparts):
        return [ self.parts[i] for i in range(1,numparts+1)]

def recPartition(a,m,B,N,accu=[]):
    # helper function generates all partitions of m
    if m == 0:
        accu.append(a.dump(N))
    else:
        for i in range(1, min([B,m])+1):
            a.parts[N+1] = i
            recPartition(a,m-i,i,N+1,accu)
    return accu

def genPartitions(m,n):
    # generates a list of all partitions of m into at most n parts
    a = Partition(m)
    return [x for x in recPartition(a,m,m,0) if len(x) <= n]

def bins(m,n):
    #all possible ways to distribute m bricks into n bins
    res = []
    for p in genPartitions(m,n):
        while len(p)< n:   p+=[0]
        for i in range(nperm(p)):   res.append(anagram(p,i))
    return res

def test():
    #test function bins
    numbricks, numbins = 3,4
    bb = bins(numbricks, numbins)
    print len(bb)
    for x in bb:
        print x

if __name__ == '__main__':
    test()


output:

>d:\python23\pythonw -u bins.py
20
[1, 1, 1, 0]
[1, 1, 0, 1]
[1, 0, 1, 1]
[0, 1, 1, 1]
[2, 1, 0, 0]
[2, 0, 1, 0]
[2, 0, 0, 1]
[1, 2, 0, 0]
[1, 0, 2, 0]
[1, 0, 0, 2]
[0, 2, 1, 0]
[0, 2, 0, 1]
[0, 1, 2, 0]
[0, 1, 0, 2]
[0, 0, 2, 1]
[0, 0, 1, 2]
[3, 0, 0, 0]
[0, 3, 0, 0]
[0, 0, 3, 0]
[0, 0, 0, 3]
>Exit code: 0




More information about the Python-list mailing list