Improve this recursive code please!
Anton Vredegoor
anton at vredegoor.doge.nl
Mon May 12 05:58:21 EDT 2003
Steven Taschuk <staschuk at telusplanet.net> wrote:
>Arrange m Os and n-1 |s in a row. The |s are bin boundaries; the
>Os are bricks. Example, with eight bricks in four bins:
> O O O | O | | O O O O
>That's the arrangement (3, 1, 0, 4).
>
>This is equivalent to replacing n-1 of m+n-1 Os with |s, so
>there's m+n-1 choose n-1 ways to do it. (Note that m+n-1 choose m
>= m+n-1 choose n-1.)
Thanks. This means one could also use the code below. * Warning, wheel
reinvention ahead :-) * This implementation has an advantage over the
generator approach because it indexes a specific arrangement
instantly, without having to go through all the previous arrangements.
Anton
def starters(L):
#return a list of 2-tuples containing info about list L
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)
for i in R:
if not bf[i]:
yield i,np*L[i:].count(L[i])/n
def uniquePermute(L,index=0):
#return an unique permutation 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 arrangement(m,n,index):
#return an indexed arrangement of m bricks in n bins
L = list("0"*m+"1"*(n-1))
s = "".join(uniquePermute(L,index))
return map(len,s.split("1"))
def countArrangements(m,n):
#count the number of arrangements of m bricks in n bins
def noverk(n,k):
#compute n over k
return reduce(lambda a,b: a*(n-b)/(b+1),range(k),1)
return(noverk(m+n-1,m))
def test():
bricks, bins = 4,4
for i in xrange(countArrangements(bricks,bins)):
print "%3s %15s" %(i,arrangement(bricks,bins,i))
if __name__=='__main__':
test()
More information about the Python-list
mailing list