Pythonic idioms / Programming Puzzle

Jason Orendorff jason at jorendorff.com
Sat Jan 19 15:18:10 EST 2002


ameoba wrote:
> Obviously, both of these solutions are correct and
> fully functional, but is one a more Pythonic way of solving the
> problem, or is there an even more Pythonic solution floating
> arround?

I'm rather fond of

-------------
def choices(menulist):
    def permute(L1, L2):
        return [a + ' ' + b  for a in L1  for b in L2]
    for combo in reduce(permute, menulist, [""]):
        print combo
-------------

which is arguably iterative.

As an interesting analog to your iterative rendering,
the generators in Python 2.2 seem chiefly aimed at
providing interesting new solutions to such puzzles.
The advantage of using a generator is that it requires
very little memory, since you can walk through the
results without building a huge list of them.

(Generators have proven pleasantly useless for almost
every real-world task I have tried them with. :)

Here I've separated the generation of the indexes
from the string handling.

-------------
from __future__ import generators

def genTuples(dims):
    N = len(dims)
    counters = [0] * N
    while 1:
        yield tuple(counters)

        # Increment the counters.
        for i in range(N):
            counters[i] += 1
            if counters[i] >= dims[i]:
                counters[i] = 0  # Overflow to next index.
            else:
                break  # No overflow; we're done.
        else:
            # Ran out of indices to increment.
            # This is our terminating condition.
            return

def genChoices(menulist):
    from operator import getitem
    for indexTuple in genTuples(map(len, menulist)):
        yield " ".join(map(getitem, menulist, indexTuple))

for order in genChoices(my_menus):
    print order
-------------

Here is the recursive solution with a generator:

-------------
from __future__ import generators

def genChoices2(menulist):
    if len(menulist) == 0:
        # Base case - one combination: the empty string.
        yield ""
        return
    first, rest = menulist[0], menulist[1:]
    for choice1 in first:
        for choice2 in gchoices(rest):
            yield choice1 + " " + choice2
-------------

## Jason Orendorff    http://www.jorendorff.com/




More information about the Python-list mailing list