I've written a simple program in Python which does the following:

Input: an integer n

Output: a 2^n x 2^n matrix containing small Ls which fill the entire matrix except one single square. Each L has it's unique number, and consists of three squares.

It's a fairly simple program, and you can see clearly what it does by typing in a few different ns.

I think this problem has an "official" name, but I'm not aware of it. If anyone knows what it's called, please let me know so I can add a link here. :)

What I'd like to do: Keep the actual algorithm as it is now (that is the rec function), but improve my C-like code to make full use of Python's features.

Code:

#!/usr/bin/env python

import sys, math

ur = [[1,0],
      [1,1]]

ul = [[0,1],
      [1,1]]

lr = [[1,1],
      [1,0]]

ll = [[1,1],
      [0,1]]

shapeCounter = 1

matrix = []

def printMatrix():
    for row in matrix:
        for element in row:
            if(element >= 10):
                print("%d" % element),
            else:
                print(" %d" % element),
        print
    print

def square(n):
    global matrix
    matrix = [[0]*(2**n) for x in xrange(2**n)]
    matrix[0][len(matrix) - 1] = -1
    rec(0, 0, len(matrix) - 1, len(matrix) - 1)
    matrix[0][len(matrix) - 1] = 0
    printMatrix()

def writeRect(rect, x, y):
    global shapeCounter
    matrix[y][x] += rect[0][0] * shapeCounter
    matrix[y+1][x] += rect[1][0] * shapeCounter
    matrix[y][x+1] += rect[0][1] * shapeCounter
    matrix[y+1][x+1] += rect[1][1] * shapeCounter
    shapeCounter += 1

def rec(sx, sy, 
        ex, ey):
    if(ex - sx < 1 or ey - sy < 1):
        return
    #print("(%d,%d) (%d,%d)" %(sx,sy,ex,ey))

    if(matrix[sy][sx] != 0):
        rect = ul
    elif(matrix[ey][sx] != 0):
        rect = ll
    elif(matrix[sy][ex] != 0):
        rect = ur
    elif(matrix[ey][ex] != 0):
        rect = lr

    hx = sx + (ex - sx) / 2
    hy = sy + (ey - sy) / 2

    writeRect(rect, hx, hy)

    rec(sx, sy, hx, hy)
    rec(hx + 1, sy, ex, hy)
    rec(sx, hy + 1, hx, ey)
    rec(hx + 1, hy + 1, ex, ey)

if __name__=='__main__':
    square(int(sys.argv[1]))
share|improve this question
1  
Get out of the habit of using global variables like that. You're just asking for trouble when you do. – Jeff Mercado Sep 23 '12 at 19:19

1 Answer

up vote 2 down vote accepted
#!/usr/bin/env python

import sys, math

ur = [[1,0],
      [1,1]]

ul = [[0,1],
      [1,1]]

lr = [[1,1],
      [1,0]]

ll = [[1,1],
      [0,1]]

Rather then creating four separate variables, I'd suggest making a list. I'd also suggest using the numpy library for its array type. It makes working with 2D arrays much nicer then using lists of lists.

shapeCounter = 1

matrix = []

Don't use global variables. Instead, pass matrix in as the parameter to the function.

def printMatrix():
    for row in matrix:
        for element in row:
            if(element >= 10):

Parens aren't needed here

                print("%d" % element),
            else:
                print(" %d" % element),
        print
    print

Note that if you used numpy, that library would already be able to nicely print a matrix.

def square(n):
    global matrix

This function should really create and return the matrix

    matrix = [[0]*(2**n) for x in xrange(2**n)]

In numpy, this would be matrix = numpy.zeros( (2**n, 2**n) )

    matrix[0][len(matrix) - 1] = -1
    rec(0, 0, len(matrix) - 1, len(matrix) - 1)
    matrix[0][len(matrix) - 1] = 0
    printMatrix()

Functions that do work on your variables shouldn't print them. Your main control function should do the printing.

def writeRect(rect, x, y):
    global shapeCounter

This isn't a terrible use of a global, but I'd avoid it. I'd have an object this attribute was stored on.

    matrix[y][x] += rect[0][0] * shapeCounter
    matrix[y+1][x] += rect[1][0] * shapeCounter
    matrix[y][x+1] += rect[0][1] * shapeCounter
    matrix[y+1][x+1] += rect[1][1] * shapeCounter
    shapeCounter += 1

def rec(sx, sy, 
        ex, ey):

I wouldn't use abbreviations. Use start_x, end_y to make your code clearer.

    if(ex - sx < 1 or ey - sy < 1):
        return
    #print("(%d,%d) (%d,%d)" %(sx,sy,ex,ey))

    if(matrix[sy][sx] != 0):
        rect = ul
    elif(matrix[ey][sx] != 0):
        rect = ll
    elif(matrix[sy][ex] != 0):
        rect = ur
    elif(matrix[ey][ex] != 0):
        rect = lr

You don't need all those parens

    hx = sx + (ex - sx) / 2
    hy = sy + (ey - sy) / 2

    writeRect(rect, hx, hy)

    rec(sx, sy, hx, hy)
    rec(hx + 1, sy, ex, hy)
    rec(sx, hy + 1, hx, ey)
    rec(hx + 1, hy + 1, ex, ey)

if __name__=='__main__':
    square(int(sys.argv[1]))
share|improve this answer
In newer versions of python, print is deprecated as a keyword and requires brackets like any other function. – Aleksandar Sep 24 '12 at 18:57
@Aleksandar, when I said the parens are unnecessary, I'm referring to the if statement, not print. – Winston Ewert Sep 24 '12 at 19:00
Your code view segment shows print, that's what led me to my conclusion. :) – Aleksandar Sep 24 '12 at 19:02
You'll see that may comments are always after the code they are commenting on, not before. But I might still object to the usage here for being inconsistent. – Winston Ewert Sep 24 '12 at 19:04

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

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