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.
2 Answers 2
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.
-
\$\begingroup\$ Thanks +1 :) How does the indenting logic work? And what is the
spacing
parameter? \$\endgroup\$ᔕᖺᘎᕊ– ᔕᖺᘎᕊ2015年10月30日 22:11:56 +00:00Commented Oct 30, 2015 at 22:11 -
1\$\begingroup\$ @ᔕᖺᘎᕊ Spacing indicates the number of spaces between numbers. Indenting logic is just a subtraction \$\endgroup\$Caridorc– Caridorc2015年10月31日 09:30:41 +00:00Commented Oct 31, 2015 at 9:30