GOTO (was Re: Appeal for python developers)

Paul McGuire ptmcg at austin.rr.com
Sat Mar 5 20:27:30 CET 2005


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




More information about the Python-list mailing list