# Multiplication Grid function

I've made a small function to output a multiplication grid (those things from primary school! :P) to an inputted number.

def make_grid(max):
max += 1  # so the for loops go up to the desired number, inclusive
print('X\t' + '\t'.join([str(_) for _ in range(max)]) + '\n')  # print all the numbers hoizontally
for i in range(max):
print(i, end="\t")  # print the vertical column of base numbers
for x in range(max):
print(str(i*x), end="\t")  # multiply the two numbers
print('\n')

if __name__ == "__main__":
try:
max = int(input("Max Number? "))
make_grid(max)
except ValueError:
print("Please enter a number!")

Choosing a max number of 5 (make_grid(5)) would output:

X 0   1   2   3   4   5

0 0   0   0   0   0   0

1 0   1   2   3   4   5

2 0   2   4   6   8   10

3 0   3   6   9   12  15

4 0   4   8   12  16  20

5 0   5   10  15  20  25

I'm looking for any improvements I could make, especially the \t's - as I use them to line up the numbers, but the gap gets pretty big, unnecessarily.

make_grid() isn't quite the right name for this function, as it is printing a grid rather than returning a grid. I think you would be better off returning a long string to be printed.

In your list comprehension, _ is a bad choice for the iteration variable name, since _ indicates a throwaway value, by convention. If you then call str(_), you should pick a different name.

Besides the excessively wide spacing as you have observed, using tabs is problematic because the output would be better with the entries right-aligned. You also have a superfluous tab at the end of each line (except the header row).

### Suggested solution

Use '{0:>{width}}'.format(…) to print the entries right-aligned with a fixed width.

def multiplication_grid(max):
max += 1    # Inclusive upper bound for ranges
grid = [['X'] + [j for j in range(max)]] + \
[[i] + [i * j for j in range(max)] for i in range(max)]

# Use fixed-width right alignment for every entry in the 2D grid
width = 2 + len(str(max * max))
fmt = lambda n: '{0:>{width}}'.format(n, width=width)
return '\n\n'.join(''.join(fmt(entry) for entry in row) for row in grid)

[['X'] + [j for j in range(max)]] creates the header row.

[[i] + [i * j for j in range(max)] for i in range(max)] is a nested list comprehension to create the rest of the rows, where i is the row number and j is the column number.

lambda is a way to define very simple functions that do nothing more than returning an expression. The lambda could also have been written as:

def fmt(n):
return '{0:>{width}}'.format(n, width=width)

The last line applies fmt() to every entry in the two-dimensional grid and joins everything into a single string.

Your code is ok, but make_grid does not only make a grid, it also prints it nicely.

Remember, one function, one task.

I would use two functions:

def make_grid(limit):
return [[i * j for i in range(limit)] for j in range(limit)]

make_grid just builds a grid as a list of lists of numbers, the way the computer likes it. We may use this output as the input to a variety of other functions.

def print_numeric_grid(grid, spacing):
for line in grid:
print(''.join(' ' * (spacing - len(str(i))) + str(i) for i in line))

print_numeric_grid has an easy job, the grid already exists so printing it is a piece of cake. Most of the logic is to indent it all nicely, without that the code would be even simpler.

• Thanks +1 :) How does the indenting logic work? And what is the spacing parameter? Oct 30, 2015 at 22:11
• @ᔕᖺᘎᕊ Spacing indicates the number of spaces between numbers. Indenting logic is just a subtraction Oct 31, 2015 at 9:30