Pythonic idioms / Programming Puzzle

ameoba ahmebah at hotmail.com
Sat Jan 19 08:51:51 EST 2002


The other day, I got caught up in nostalgia, and decided to look around at 
some LOGO (y'know, turtle graphics &C) webzits.  What to my wondering eyes 
should appear but an acknowledgement that LOGO is a variant of LISP and -
not- just a toy language.  To prove it there was an example program ( 
http://www.cs.berkeley.edu/~bh/logo-sample.html ) that printed permutations  
of an arbitrary list of arbitrarily long lists of strings.


in 4 lines.


Python's a new thing for me, so in my newborn zeal, I decided to show that 
Python could do it just as well, using lists defined like:

-------------
list = [["Small","Medium","Large"],
        ["Mountain Dew", "root beer", "orange juice"],
        ["\b, a"],
        ["hamburger", "cheeseburger", "double cheeseburger"],
        ["\b, and a"],
        ["small", "medium", "large"],
        ["fries."]]
-------------

So I essentially translated it to Python, which resulted in this:
----------
#recursive arbitrary list of lists permuter.
def choices(menu, sofar = ""):
    if(menu == []) : print sofar.strip()
    else : 
        for x in menu[0] : choices(menu[1:],sofar+" "+x)
----------


Which was fine and dandy, but I couldn't stop with simply translating 
somebody elses work.  I wanted to come up with an iterative solution, which 
gave me :

----------
# arbitrary list of lists permuter.  Iterative version.
# Esentially a series of different base N counters 
# where N is determined by the length of the corresponding list
# with overflows carried over to the next place
def ichoices(menulist = []):
    #init counter
    counter = [0]*len(menulist)

    #loop 'till counter overruns on last element
    # (god I love reverse array indexing, sweet syntactic sugar)
    while counter[-1] < len(menulist[-1]):
        #build & print the combination
        t = ""
        for x in range(len(menulist)):
            t += " " + menulist[x][counter[x]]
        print t.strip()

        #increment counter, and handle overflows by carry to next place
        #except for the last place, since the overflow there
        #is our termination condition
        counter[0] += 1
        for x in range(len(counter)-1):
            if counter[x] >= len(menulist[x]):
                counter[x] = 0
                counter[x+1] += 1
----------

Which, at 12 lines of code, is longer but (perhaps just because I wrote it) 
a bit easier to follow.

Looking at these two fundamentally different solutions to the same problem 
got me thinking...  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?

Another question;  Does my code show that I have any perceptable 'accent'? 
That is to ask, am I obviously influenced by the other languages I've 
worked in (mostly C/Java/C++)?



More information about the Python-list mailing list