[EMAIL PROTECTED] (Alex Martelli) wrote: > Without any specification regarding the distributions required for the > "5 random numbers" it's really impossible to say whether these are > better or worse than other proposed solutions.
FWIW, I decided it would be fun to see what kind of implementation I could come up test driven and avoiding reading the thread or background references too much first. So starting from: import unittest def partition(total, n, min): return [50] class PartitionTests(unittest.TestCase): def testsinglevalue(self): self.assertEqual([50], partition(50, 1, 1)) if __name__=='__main__': unittest.main() I eventually worked my way through 15 revisions to the code below. The tests were added in the order you see them below. The commented out function is the one I had arrived at before I added the first distribution test which triggered a major refactor (although the code ended up remarkably similar): if you uncomment it all but the distribution tests pass. I don't really like the arbitrary limits for the distribution tests, but I'm not sure how else to test that sort of thing. And as Alex said, without knowing what distribution the OP wanted the definition I chose to use is completely arbitrary. ----- partition.py ------- import unittest, collections from random import randint, sample def partition(total, n, min): maxtotal = total - n*(min-1) posts = sorted(sample(xrange(1, maxtotal), n-1)) return [ (b-a)+min-1 for (a,b) in zip([0]+posts, posts+[maxtotal]) ] # def partition(total, n, min): # maxtotal = total - (n*min) # sums = sorted(randint(0, maxtotal) for i in range(n-1)) # return [(b-a)+min for (a,b) in zip([0]+sums, sums+[maxtotal])] class PartitionTests(unittest.TestCase): def testsinglevalue(self): self.assertEqual([50], partition(50, 1, 1)) def testnvalues(self): self.assertEqual([1]*5, partition(5, 5, 1)) def testnminusone(self): self.assertEqual([1]*4+[2], sorted(partition(6, 5, 1))) def testnminusone2(self): # Check we get all possible results eventually expected = set([(1,1,2), (1,2,1), (2,1,1)]) for i in range(100): got = tuple(partition(4,3,1)) if got in expected: expected.remove(got) if not len(expected): break self.assertEqual(len(expected), 0) def testdistribution(self): # Make sure we get each of 3 possible outcomes roughly # equally often. actual = collections.defaultdict(int) for i in range(1000): actual[tuple(partition(4,3,1))] += 1 counts = actual.values() assert (min(counts) > 250) assert (max(counts) < 400) def testdistribution2(self): # More arbitrary limits for the distribution. 10 possible # outcomes this time. actual = collections.defaultdict(int) ntries = 10000 for i in range(ntries): actual[tuple(partition(6,3,1))] += 1 counts = actual.values() assert (min(counts) > 900) assert (max(counts) < 1100) def testmintwo(self): self.assertEqual([2]*50, partition(100,50,2)) def testminzero(self): self.assertEqual([0]*20, partition(0,20,0)) def testcantdoit(self): self.assertRaises(ValueError, partition, 100, 51, 2) if __name__=='__main__': unittest.main() -------------------------- -- http://mail.python.org/mailman/listinfo/python-list