At the risk of beating this into the Pythonic ground, here is a
generator version which collapses the original nested loop into a
single loop, so that break works just fine:
..def getCombinations(*args):
.. if len(args) > 1:
.. for a0 in args[0]:
.. for remainder in getCombinations(*args[1:]):
.. yield [a0]+remainder
.. else:
.. for a0 in args[0]:
.. yield [a0]
..
..for i,j,k in getCombinations(xrange,yrange,zrange):
.. if lookup(i,j,k) == target:
.. print "Eureka!"
.. break
..else:
.. print "Rats! No match found."
Now that we have getCombinations in our toolkit, we can also do things
like:
..numbers = range(2)
..colors = ['red','green','blue','orange','white']
..sizes = ['S','M','L','XL','XXL']
..letters = "ABCDE"
..print [ c for c in getCombinations(numbers, colors) ]
..print [ c for c in getCombinations(numbers, colors, sizes) ]
..print [ c for c in getCombinations(letters,colors) ]
..print [ c for c in getCombinations(letters,letters) ] # take letters
two at a time
..print [ "".join(c) for c in getCombinations(letters,letters) ]
giving:
[[0, 'red'], [0, 'green'], [0, 'blue'], [0, 'orange'], [0, 'white'],
[1, 'red'], [1, 'green'], [1, 'blue'], [1, 'orange'], [1, 'white']]
[[0, 'red', 'S'], [0, 'red', 'M'], [0, 'red', 'L'], [0, 'red', 'XL'],
[0, 'red', 'XXL'], [0, 'green', 'S'], [0, 'green', 'M'], [0, 'green',
'L'], [0, 'green', 'XL'], [0, 'green', 'XXL'], [0, 'blue', 'S'], [0,
'blue', 'M'], [0, 'blue', 'L'], [0, 'blue', 'XL'], [0, 'blue', 'XXL'],
[0, 'orange', 'S'], [0, 'orange', 'M'], [0, 'orange', 'L'], [0,
'orange', 'XL'], [0, 'orange', 'XXL'], [0, 'white', 'S'], [0, 'white',
'M'], [0, 'white', 'L'], [0, 'white', 'XL'], [0, 'white', 'XXL'], [1,
'red', 'S'], [1, 'red', 'M'], [1, 'red', 'L'], [1, 'red', 'XL'], [1,
'red', 'XXL'], [1, 'green', 'S'], [1, 'green', 'M'], [1, 'green', 'L'],
[1, 'green', 'XL'], [1, 'green', 'XXL'], [1, 'blue', 'S'], [1, 'blue',
'M'], [1, 'blue', 'L'], [1, 'blue', 'XL'], [1, 'blue', 'XXL'], [1,
'orange', 'S'], [1, 'orange', 'M'], [1, 'orange', 'L'], [1, 'orange',
'XL'], [1, 'orange', 'XXL'], [1, 'white', 'S'], [1, 'white', 'M'], [1,
'white', 'L'], [1, 'white', 'XL'], [1, 'white', 'XXL']]
[['A', 'red'], ['A', 'green'], ['A', 'blue'], ['A', 'orange'], ['A',
'white'], ['B', 'red'], ['B', 'green'], ['B', 'blue'], ['B', 'orange'],
['B', 'white'], ['C', 'red'], ['C', 'green'], ['C', 'blue'], ['C',
'orange'], ['C', 'white']]
[['A', 'A'], ['A', 'B'], ['A', 'C'], ['B', 'A'], ['B', 'B'], ['B',
'C'], ['C', 'A'], ['C', 'B'], ['C', 'C']]
['AA', 'AB', 'AC', 'BA', 'BB', 'BC', 'CA', 'CB', 'CC']
Finally, these last two examples make me think of permutations as well
(in which order is significant - can't count both AB and BA). So here
is a brute force version of getPermutations, built on getCombinations,
but filtering previously reported duplicates:
..from sets import Set as set
..def getPermutations(*args):
.. prevs = []
.. for comb in getCombinations(*args):
.. thisComb = set(comb)
.. if not thisComb in prevs:
.. prevs.append(thisComb)
.. yield comb
..
..print [ c for c in getPermutations(letters,letters) ]
..print [ "".join(c) for c in getPermutations(letters,letters) ]
gives:
[['A', 'A'], ['A', 'B'], ['A', 'C'], ['B', 'B'], ['B', 'C'], ['C',
'C']]
['AA', 'AB', 'AC', 'BB', 'BC', 'CC']
-- Paul