6
\$\begingroup\$

I'm just playing with Python, trying to refamiliarize myself with it since I haven't used it in a few years. I'm using Python3, but as far as I know it could easily be Python2 with a change to the print statements. What I'm generating is something similar to GitHub's Identicons.

I know of two possible issues, one is that I don't account for an odd width, and the other is that my fill string will be reversed on the symmetric half, so I can't use something like [ ].

import random

def generateConnectedAvatar(fill="XX", empty="  ", height=10, width=10, fillpercent=0.4):
    halfwidth = int(width/2)
    painted = 0
    maxPainted = height*halfwidth*fillpercent
    adjacent = [(-1,-1), (-1,0), (-1,1), (0,1), (0,-1), (1,-1), (1,0), (1,1)]
    # initialize a blank avatar                                                                                         
    avatar = [[empty for w in range(halfwidth)] for h in range(height)]
    # 'paint' a single cell and add it to the stack                                                                     
    y, x = random.randint(0,height-1), random.randint(0,halfwidth-1)
    lst = [(y,x)]
    while (len(lst) != 0):
        # Take the first element off the list                                                                           
        y, x = lst.pop()
        # Determine if we should paint it                                                                               
        if painted <= maxPainted:
            avatar[y][x] = fill
            painted += 1
            # Find all available neighbors and add them to the list (in a random order)                                 
            # shuffle our adjacent positions table                                                                      
            random.shuffle(adjacent)
            for posy, posx in adjacent:
                tmpy, tmpx = y + posy, x + posx
                if tmpx >= 0 and tmpx < halfwidth:
                    if tmpy >= 0 and tmpy < height:
                        # Make sure we haven't already painted it                                                       
                        if avatar[tmpy][tmpx] is not fill:
                            lst.append((tmpy,tmpx))
    # output the result (symmetrically)                                                                                 
    #   (in our case, just printing to console)                                                                         
    for h in range(height):
        half = ""
        for w in range(halfwidth):
            half += avatar[h][w]
        print(half + half[::-1])

The output can be pretty neat looking sometimes, but it's frequently very blocky, so I'll probably want to figure out some sort of spacing algorithm.

Some sample output:

  XX            XX  
XXXXXX        XXXXXX
XXXX            XXXX
XXXX            XXXX
  XX            XX  
    XX        XX    
XXXX  XX    XX  XXXX
XXXXXX        XXXXXX
XXXX    XXXX    XXXX
    XXXX    XXXX
\$\endgroup\$
3
\$\begingroup\$

This is quite neat. I suggest some improvements though.

The method does two things: it generates an identicon and then prints it. It would be better to split these two operations so that you can have functions that follow the single responsibility principle.

The while loop condition can be simplified to be more pythonic:

while lst:

The range conditions can be simplified too:

if 0 <= tmpx < halfwidth:

Your naming and spacing should follow PEP8, the python style guide.

\$\endgroup\$
  • \$\begingroup\$ While I get started skimming through this style guide, are there things that you could quickly point out? The spacing looks right to me, and so far the only things I break are the 80 character limit in a few places (since I'm using a 120 width terminal) and the underscore_naming_convention. \$\endgroup\$ – agweber Jun 10 '15 at 21:20
  • \$\begingroup\$ Thee naming you found, the spacing is not right: put space around operators, for example width / 2, and when you set maxWidth, and so on \$\endgroup\$ – janos Jun 11 '15 at 4:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.