HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Optimizing Multiplication Table

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
optimizingtablemultiplication

Problem

I have a class that takes an array of integers and produces a multiplication table.

class MultiplicationTable
  def initialize(num_ary)
    @num_ary = num_ary.to_a
  end         

  def generate             
    a1 = @num_ary.clone    
    a2 = @num_ary.clone    

    rows = []              
    rows << a1             

    a2.shift               

    a2.each do |x|         
      cols = [x]           
      a1[1..-1].each do |y|
        cols << (x * y)    
      end                  
      rows << cols         
    end                    

    rows                   
  end                      
end


So this:

MultiplicationTable.new(1.upto(5)).generate


produces this output:

[
  [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] 
]


Here are my results from benchmarking:

user     system      total        real
100 entry table      0.000000   0.000000   0.000000 (  0.001295)
1,000 entry table    0.120000   0.010000   0.130000 (  0.132325)
10,000 entry table  15.290000   0.380000  15.670000 ( 15.747799)


Is there anything I can do to speedup/improve up this code?

Solution

You only need to compute half the table because it is symmetrical; for your line

a1[1..-1].each do |y|


instead do

a1[x..-1].each do |y|


and if you ever need to look up a b where b > a, instead look up b a

This will create a multiplication table that looks like this:

# old table
  1  2  3  4  5
1 1  2  3  4  5
2 2  4  6  8 10
3 3  6  9 12 15
4 4  8 12 16 20
5 5 10 15 20 25

# new table
  1 2 3  4  5
1 1 2 3  4  5
2   4 6  8 10
3     9 12 15
4       16 20
5          25

# final multiplication table
arr = [
  [1,2,3,4,5],
  [4,6,8,10],
  [9,12,15],
  [16,20],
  [25]
]


To access a*b where a >= b, the answer is in arr[a-1][b-a]

To access 3*4, the answer is in row 3-1, element 4-3 = arr[3-1][4-3] = arr[2][1] = 12

To access 52 (= 25), the answer is in row 2-1, element 5-2 = arr[2-1][5-2] = arr[1][3] = 10

To access 100x100 (assuming the range goes high enough), arr[99][0]

You'll need to do something slightly different if you are passing an array that isn't 1..x - in that case, first look up the index of each of the two numbers in the original array and use THEM in the arr[a-1][b-a] lookup. I suspect you'll need to subtract 1 from the indices but I haven't worked it out in my head.

Code Snippets

a1[1..-1].each do |y|
a1[x..-1].each do |y|
# old table
  1  2  3  4  5
1 1  2  3  4  5
2 2  4  6  8 10
3 3  6  9 12 15
4 4  8 12 16 20
5 5 10 15 20 25

# new table
  1 2 3  4  5
1 1 2 3  4  5
2   4 6  8 10
3     9 12 15
4       16 20
5          25

# final multiplication table
arr = [
  [1,2,3,4,5],
  [4,6,8,10],
  [9,12,15],
  [16,20],
  [25]
]

Context

StackExchange Code Review Q#81884, answer score: 2

Revisions (0)

No revisions yet.