Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.

Friday, May 3, 2013

Nested loops: Magic square

Problem: Print magic square for odd ones.  A magic square is an arrangement of numbers in a square grid, where the numbers in each row, and in each column, and the numbers that run diagonally in both directions, all add up to the same number

Example: if n = 3, print the following square:


8 1 6 
3 5 7 
4 9 2 

If n = 5, print the following square:

17 24  1  8 15 
23  5  7 14 16 
 4  6 13 20 22 
10 12 19 21  3 
11 18 25  2  9 


Algorithm:

Start in the central column of the first row with the number 1.

After that, the fundamental movement for filling the squares is diagonally up and right, one step at a time.

If a filled square is encountered, one moves vertically down one square instead, then continues as before.

When an "up and to the right" move would leave the square, it is wrapped around to the last row or first column, respectively.


Solution in Python:

def magic_square_odd(n):

    """
    Author: Mayur P Srivastava
    n must be a positive and odd number.
    """
    assert n > 0 and n % 2 == 1

    matrix = create_matrix(n)

    row = 0
    col = int((n - 1) / 2)

    matrix[row][col] = 1

    for i in range(1, n*n):
        row_new = row - 1
        col_new = col + 1

        if row_new >= 0 and col_new < n:
            if matrix[row_new][col_new] > 0:
                row = row + 1
                assert matrix[row][col] == 0
            else:
                row = row_new
                col = col_new
        elif row_new < 0 and col_new == n:
            row = row + 1
            assert matrix[row][col] == 0
        elif row_new < 0:
            row = n - 1
            col = col_new
        else:
            row = row_new
            col = 0

        matrix[row][col] = i + 1

    print stringify_magic_square(matrix)


def stringify_magic_square(matrix):
    n = len(matrix)
    format_number = "%%%dd " % len(str(n * n))

    s = ""
    for row in matrix:
        str_row = ""
        for e in row:
            str_row += format_number % e
        s = s + str_row + "\n"

    return s


def create_matrix(n, value=0):
    matrix = []
    for i in range(n):
        row = []
        for j in range(n):
            row.append(value)
        matrix.append(row)
    return matrix


Concepts learned: nested loops.

No comments:

Post a Comment