How to Perform Vector Addition in Ruby

How do I perform vector addition in Ruby?

See the Vector class:

require "matrix"

x = Vector[100, 100]
y = Vector[2, 3]
print x + y

E:\Home> ruby t.rb
Vector[102, 103]

See vectorops for additional operations on vectors:

… the following operations work like expected

  v1 = Vector[1,1,1,0,0,0]
v2 = Vector[1,1,1,1,1,1]

v1[0..3]
# -> Vector[1,1,1]

v1 += v2
# -> v1 == Vector[2,2,2,1,1,1]

v1[0..3] += v2[0..3]
# -> v1 == Vector[2,2,2,0,0,0]

v1 + 2
# -> Vector[3,3,3,1,1,1]

See also vectorops.

How to sum array of numbers in Ruby?

Try this:

array.inject(0){ |sum, x| sum + x }

See Ruby's Enumerable Documentation

(note: the 0 base case is needed so that 0 will be returned on an empty array instead of nil)

ruby: sum corresponding members of two or more arrays

Here's the transpose version Anurag suggested:

[[1,2,3], [4,5,6]].transpose.map {|x| x.reduce(:+)}

This will work with any number of component arrays. reduce and inject are synonyms, but reduce seems to me to more clearly communicate the code's intent here...

How do I add columns and rows to a Matrix in Ruby?

Since doing this isn't (so far as I know) a valid matrix operation in the mathematical sense, there's nothing to do this in place. You can create a new Matrix though:

m = Matrix.diagonal(1, 2, 3)
#=> Matrix[[1, 0, 0], [0, 2, 0], [0, 0, 3]]

Matrix.columns(m.to_a << [4, 5, 6])
#=> Matrix[[1, 0, 0, 4], [0, 2, 0, 5], [0, 0, 3, 6]]

Matrix.rows(m.to_a << [4, 5, 6])
#=> Matrix[[1, 0, 0], [0, 2, 0], [0, 0, 3], [4, 5, 6]]

This uses columns or rows to create a new matrix by adding a new array
to the array representation of the original matrix.

Algorithm implemented in ruby to add one to a number represented as an array

while new_number > 0
result.push new_number%10
new_number /= 10
end

Even though at first glance this loop seems to be O(n), it is at least Ω(n²).

Since big numbers in Ruby are stored and processed as arrays of binary digits (digits in base 2³²), division by 10 is a costly operation. The exact time complexity depends on the division algorithm Ruby uses, but new_number /= 10 will have to process all of the new_number's binary digits, so it cannot be faster than O(n).

What's the efficient way to multiply two arrays and get sum of multiplied values in Ruby?

Update

I've just updated benchmarks according to new comments. Following Joshua's comment, the inject method will gain a 25% speedup, see array walking without to_a in the table below.

However since speed is the primary goal for the OP we have a new winner for the contest which reduces runtime from .34 to .22 in my benchmarks.

I still prefer inject method because it's more ruby-ish, but if speed matters then the while loop seems to be the way.

New Answer

You can always benchmark all these answers, I did it for curiosity:

> ./matrix.rb 
Rehearsal --------------------------------------------------------------
matrix method 1.500000 0.000000 1.500000 ( 1.510685)
array walking 0.470000 0.010000 0.480000 ( 0.475307)
array walking without to_a 0.340000 0.000000 0.340000 ( 0.337244)
array zip 0.590000 0.000000 0.590000 ( 0.594954)
array zip 2 0.500000 0.000000 0.500000 ( 0.509500)
while loop 0.220000 0.000000 0.220000 ( 0.219851)
----------------------------------------------------- total: 3.630000sec

user system total real
matrix method 1.500000 0.000000 1.500000 ( 1.501340)
array walking 0.480000 0.000000 0.480000 ( 0.480052)
array walking without to_a 0.340000 0.000000 0.340000 ( 0.338614)
array zip 0.610000 0.010000 0.620000 ( 0.625805)
array zip 2 0.510000 0.000000 0.510000 ( 0.506430)
while loop 0.220000 0.000000 0.220000 ( 0.220873)

Simple array walking wins, Matrix method is worse because it includes object instantiation. I think that if you want to beat the inject while method (to beat here means an order of magnitude fastest) you need to implement a C extension and bind it in your ruby program.

Here it's the script I've used

#!/usr/bin/env ruby

require 'benchmark'
require 'matrix'

array_A = [1, 2, 1, 4, 5, 3, 2, 6, 5, 8, 9]
array_B = [3, 2, 4, 2, 5, 1, 3, 3, 7, 5, 4]

def matrix_method a1, a2
(Matrix.row_vector(a1) * Matrix.column_vector(a2)).element(0,0)
end

n = 100000

Benchmark.bmbm do |b|
b.report('matrix method') { n.times { matrix_method(array_A, array_B) } }
b.report('array walking') { n.times { (0...array_A.count).to_a.inject(0) {|r, i| r + array_A[i]*array_B[i]} } }
b.report('array walking without to_a') { n.times { (0...array_A.count).inject(0) {|r, i| r + array_A[i]*array_B[i]} } }
b.report('array zip') { n.times { array_A.zip(array_B).map{|i,j| i*j }.inject(:+) } }
b.report('array zip 2') { n.times { array_A.zip(array_B).inject(0) {|r, (a, b)| r + (a * b)} } }
b.report('while loop') do
n.times do
sum, i, size = 0, 0, array_A.size
while i < size
sum += array_A[i] * array_B[i]
i += 1
end
sum
end
end
end


Related Topics



Leave a reply



Submit