Forum: Ruby Too Much Matrix: Iterating over Each matrix cell w/o passing the complete thing all the time?

614c621eef67a8fb4fafe71a2ed166e2?d=identicon&s=25 James Joyce (yyoyo)
on 2013-09-01 00:07
Attachment: not_so_elegant_iteration.rb (882 Bytes)
Okay, where to start?

Sounds like the beginning of a joke, you have a fancy data table, a
splendid output table and a method. You use the method to calculate a
splendid number out of the data table and store it in the output table.
Similar to taking a bean out of the jar and putting it into another
nicer jar.

How do you get the input-data-table value into the method without
passing the whole table as an argument all the time?

The problem is that I iterate the same calculation over all cells, which
is not a problem for four, nine, or 25 cells, but it could be one if
this runs on 100x100 matrices.

This maybe about basic instance/symbol/variable scoping, but I'm not
sure and so far I had avoided dealing with them. So, please, someone
needs to explain me what I actually look for, is there a better way than
passing the complete table into the method?

Thanks in advance,
 the Force may be with you---always.

 yours James
14b5582046b4e7b24ab69b7886a35868?d=identicon&s=25 Joel Pearson (virtuoso)
on 2013-09-01 08:14
Why are you using indices? All you're doing with them is referencing the
object inside the matrix, which you already have by using nested "each"
iterators. Use "y" instead of the x & y index and then you won't have to
pass the matrix around.
2f4d4f9c35ea851bffb9a9cc2e086365?d=identicon&s=25 Harry Kakueki (Guest)
on 2013-09-01 08:43
(Received via mailing list)
>
>
> How do you get the input-data-table value into the method without
> passing the whole table as an argument all the time?
>
>
>
I have not checked speed. But, you can try this.

def mc(n)
  b = 100
  delta = n / ((n**2 + b)**0.5)
end

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

p iv.map{|a| a.map{|n| mc(n)}}



OR


require 'matrix'

def mc(n)
  b = 100 # smoothing factor
  delta = n / ((n**2 + b) ** 0.5)
end

iv = Matrix[[1,2,3],[4,5,6],[7,8,9]]
ot = iv.to_a
iv.each_with_index{|x,r,c| ot[r][c] = mc(x)}
p ot




Harry
3853dd5371ac1e094fc45d6c2aa0e459?d=identicon&s=25 Carlo E. Prelz (Guest)
on 2013-09-01 09:44
(Received via mailing list)
Subject: Too Much Matrix: Iterating over Each matrix cell w/o passing
the complete thing all the time?
  Date: dom 01 set 13 12:07:03 +0200

Quoting James Joyce (lists@ruby-forum.com):

> This maybe about basic instance/symbol/variable scoping, but I'm not
> sure and so far I had avoided dealing with them. So, please, someone
> needs to explain me what I actually look for, is there a better way than
> passing the complete table into the method?

One thing must be clear: when you pass an array (on any other object)
to a function, you do NOT put the whole array onto the stack. The only
thing that is passed is the object reference. Thus, passing a single
integer or a one-billion-element array to a function has the same
(quite small) memory requirements. Thus, if what you are writing is a
quick hack, your solution can cut the cake.

If you are after a cleaner option, one that embodies a bit more Ruby's
object-oriented spirit, you may create a class that becomes the owner
of your table. Something like this:

class Intricate_calculator
  def initialize(table)
    @table=table
  end

  def make_intricate_calculations(at_position_x,at_position_y)
    a=@table[at_position_x][at_position_y]
    b=100 # smoothing factor
    delta=a/((a**2+b)**0.5)
    return delta
  end
end

This way, you do not need to pass the table to your method each
time. Your example would look like this:

calculator=Intricate_calculator::new([[1,2,3],[4,5,6],[7,8,9]]) # fancy
output_table=Array.new(input_vectors.size){Array.new(input_vectors.size){}}
# splendid
output_table.each_with_index do |x,rowindex|
  x.each_with_index do |y,colindex|
    output_table[rowindex][colindex]=calculator.make_intricate_calculations(rowindex,colindex)
  end
end

The important thing to note here is that this solution is certainly
cleaner, but I believe you won't experience major speed gains.

Carlo
2f4d4f9c35ea851bffb9a9cc2e086365?d=identicon&s=25 Harry Kakueki (Guest)
on 2013-09-01 14:52
(Received via mailing list)
Or you could try this with the matrix approach.

require 'matrix'

def mc(n)
  b = 100
  delta = n / ((n**2 + b) ** 0.5)
end

iv = Matrix[[1,2,3],[4,5,6],[7,8,9]]
p iv.map{|x| mc(x)}


Harry
614c621eef67a8fb4fafe71a2ed166e2?d=identicon&s=25 James Joyce (yyoyo)
on 2013-09-01 19:01
«That's Bingo!»
Or, just «Bingo!»

Solutions within less than ten hours, who can claim to have such a
support? Thx guys.

I'm surprised by the «sheer» number of solutions ... I take the
Matrix#map to replace the nested Array#each and may wrap a class around
all, as Carlo had read my minds on the OO spirit.

You guys officially rock.

J.


PS: Joel, what's wrong about indices, in general?
14b5582046b4e7b24ab69b7886a35868?d=identicon&s=25 Joel Pearson (virtuoso)
on 2013-09-02 08:24
Nothing wrong with indices where necessary. I was just saying that
passing the indices was unnecessary, given that "y" was the value you
were using inside the method, but you discarded it and passed the
indices instead.
614c621eef67a8fb4fafe71a2ed166e2?d=identicon&s=25 James Joyce (yyoyo)
on 2013-09-02 14:21
I see. Right, you are. «Given» y were the one-only value in universe; so
you cannot had known. How you guys would do it with one table, so I can
do it with many, later, was what I was thinking about. Carlo sensed it
early on. Class#initialize ... @table is it, but wasn't plain to me. I
now read it's the OO-chapter two, or so, in the Pickaxe? Ouch.
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.