Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a square multiplication table in Ruby

Tags:

ruby

I got this question in an interview and got almost all the way to the answer but got stuck on the last part. If I want to get the multiplication table for 5, for instance, I want to get the output to be formatted like so:

1, 2, 3, 4, 5
2, 4, 6, 8, 10
3, 6, 9, 12, 15
4, 8, 12, 16, 20
5, 10, 15, 20, 25

My answer to this is:

def make_table(n)
  s = ""
  1.upto(n).each do |i|
    1.upto(n).each do |j|
      s += (i*j).to_s
    end
    s += "\n"
  end
  p s
end

But the output for make_table(5) is:

"12345\n246810\n3691215\n48121620\n510152025\n"

I've tried variations with array but I'm getting similar output.

What am I missing or how should I think about the last part of the problem?

like image 500
Coder_Nick Avatar asked Jun 13 '26 08:06

Coder_Nick


2 Answers

You can use map and join to get a String in one line :

n = 5 
puts (1..n).map { |x| (1..n).map { |y| x * y }.join(', ') }.join("\n")

It iterates over rows (x=1, x=2, ...). For each row, it iterates over cells (y=1, y=2, ...) and calculates x*y. It joins every cells in a row with ,, and joins every rows in the table with a newline :

1, 2, 3, 4, 5
2, 4, 6, 8, 10
3, 6, 9, 12, 15
4, 8, 12, 16, 20
5, 10, 15, 20, 25

If you want to keep the commas aligned, you can use rjust :

puts (1..n).map { |x| (1..n).map { |y| (x * y).to_s.rjust(3) }.join(',') }.join("\n")

It outputs :

  1,  2,  3,  4,  5
  2,  4,  6,  8, 10
  3,  6,  9, 12, 15
  4,  8, 12, 16, 20
  5, 10, 15, 20, 25

You could even go fancy and calculate the width of n**2 before aligning commas :

n = 11
width = Math.log10(n**2).ceil + 1
puts (1..n).map { |x| (1..n).map { |y| (x * y).to_s.rjust(width) }.join(',') }.join("\n")

It outputs :

   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11
   2,   4,   6,   8,  10,  12,  14,  16,  18,  20,  22
   3,   6,   9,  12,  15,  18,  21,  24,  27,  30,  33
   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  44
   5,  10,  15,  20,  25,  30,  35,  40,  45,  50,  55
   6,  12,  18,  24,  30,  36,  42,  48,  54,  60,  66
   7,  14,  21,  28,  35,  42,  49,  56,  63,  70,  77
   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  88
   9,  18,  27,  36,  45,  54,  63,  72,  81,  90,  99
  10,  20,  30,  40,  50,  60,  70,  80,  90, 100, 110
  11,  22,  33,  44,  55,  66,  77,  88,  99, 110, 121
like image 167
Eric Duminil Avatar answered Jun 15 '26 02:06

Eric Duminil


Without spaces between the figures, the result is indeed unreadable. Have a look at the % operator, which formats strings and numbers. Instead of

s += (i*j).to_s

you could write

s += '%3d' % (i*j)

If you really want to get the output formatted in the way you explained in your posting (which I don't find that much readable), you could do a

s += "#{i*j}, "

This leaves you with two extra characters at the end of the line, which you have to remove. An alternative would be to use an array. Instead of the inner loop, you would have then something like

s += 1.upto(n).to_a.map {|j| i*j}.join(', ') + "\n"
like image 30
user1934428 Avatar answered Jun 15 '26 01:06

user1934428