# Print multiplication tables

Write a function that given a max argument will print a nicely aligned multiplication tables, for example, if max = 8

  1   2   3   4   5   6   7   8
2   4   6   8  10  12  14  16
3   6   9  12  15  18  21  24
4   8  12  16  20  24  28  32
5  10  15  20  25  30  35  40
6  12  18  24  30  36  42  48
7  14  21  28  35  42  49  56
8  16  24  32  40  48  56  64


The code is pretty straightforward, but I am interested in any possible improvement.

def print_multiplication_table(max)
pad = (1 + (max*max).to_s.length)
puts (1..max)
.to_a
.product((1..max).to_a)
.map{|a, b| a * b}
.each_slice(max)
.map{ |x| x.map(&:to_s).map{ |x| " " * (pad - x.length) + x}.join(' ')}
.join("\n")
end

print_multiplication_table(8)


## 2 Answers

def print_multiplication_table(max)


I think size would be a better name for the argument. max sounds like it's the largest number in the table.

pad = (1 + (max*max).to_s.length)


Rename to column_width. Padding is the spaces that need to be added to reach the column width.

The parentheses aren't needed.

.map{ |x| x.map(&:to_s).map{ |x| " " * (pad - x.length) + x}.join(' ')}


join(' ') adds an extra space between columns. The 1 + in the calculation of the column width already gurantees there's at least one space between two numbers, so now there are at least two spaces between numbers.

If this is intended, change the 1 to 2 in the calculation of the column width, so the minimum number of spaces is determined in a single place in the code.

Since you only want to print the table, it is unnecessary to build all those temporary arrays and strings. A nested loop will be shorter and much easier to read than a chain of calls:

def print_multiplication_table(size)
column_width = 2 + (size*size).to_s.length
(1..size).each do |i|
(1..size).each do |j|
result = (i * j).to_s
padding = " " * (column_width - result.length)
print padding + result
end
print("\n")
end
end

• The original reads better -- and is more idiomatic ruby -- than the nested loop version. The temporary arrays are there for readability and because the performance hit doesn't matter. The other comments are good, though. – Jonah Nov 30 '15 at 0:17

Spike gave a nice answer already. I just wanted to point out one thing: This is a good use case for rjust, aka "right-justify". With that, you can skip the string-multiplication when you pad the numbers.

def print_multiplication_table(max)
padding = (max * max).to_s.length + 1
sequence = (1..max).to_a
puts sequence.product(sequence)
.map { |a, b| (a * b).to_s.rjust(padding) }
.each_slice(max)
.map(&:join)
.join("\n")
end


This one only uses 1 space between columns, but 2 spaces can be had by replacing .map(&:join) with .map { |row| row.join(" ") }.