"n choose m" module

John Lehmann jlehmann at nsw.bigpond.net.au
Fri Apr 21 03:55:17 EDT 2000


One day, in a fit of boredom when my newscientist subscription was a
week late and I was reduced to solving the enigma puzzle, I wrote a
class to generate the permutations from a list.  I assume I was wasting
my time and that would have been something in the standard libraries,
but in case anyone finds it useful...
-------------- next part --------------
"""

a class for generating permutations from an array

# choose 2 letters from 'abcd'
c = Chooser(['a', 'b', 'c', 'd'], 2)
while c.hasMoreElements():
	print c.next()

"""
import time, copy

class NoMoreChoices(StandardError):
	pass

class Chooser:
	def __init__(self, l, n):
		" generate permutations of n choices of l "
		if n > len(l):
			raise StandardError("cannot make %d choices from a list %d items long"%(n, len(l)))
		self.l = l
		self.n = n
		self.c = range(n)
		self.dirty = 0
		
	def hasMoreElements(self):
		" determine whether there more elements to generate "
		if self.c == None:
			return false
		if self.dirty:
			self.generatenext()
		return self.c <> None

	def next(self):
		" get the next element "
		if self.dirty:
			self.generatenext()
		self.dirty = 1
		return self.getmap(self.c)

	def getmap(self, c):
		m = []
		for i in c:
			m.append(self.l[i])
		return m
	
	def generatenext(self):
		# from the current choice
		self.dirty = 0
		c = self.c
		n = self.n
		ll = len(self.l)
		done = 0
		i = n - 1
		try:
			while not done:
				# take the last element and increment by 1		
				c[i] = c[i] + 1
				# check for modulo overflow
				while c[i] == ll:
					# carry the 1
					c[i] = 0
					i = i - 1
					c[i] = c[i] + 1
					if i == -1:
						raise NoMoreChoices()
				i = n - 1
				if not self.containsduplicates(c):
					done = 1
			self.c = c
		except NoMoreChoices, e:
			self.c = None

	def containsduplicates(self, c):
		" check for duplicate entries "
		for i in range(self.n):
			if c[i] in c[i + 1:]:
				return 1
		return 0


More information about the Python-list mailing list