Limited Matrices in Ruby

Limited matrices in Ruby

The designer of class Matrix must have been a fan of immutable data structures and functional programming. Yes, you are correct.

In any case, there is a simple solution for what you want. Use Matrix for what it can do, then, just use .to_a to get a real array.

>> Matrix.identity(2).to_a
=> [[1, 0], [0, 1]]

See also Numerical Ruby Narray. You could also monkeypatch the class to add more behavior. If you do this, please patch a subclass of Matrix. (There are Ruby library projects out there that want more behavior from required classes so they directly modify them, making their new files somewhat toxic. They could have so easily just patched a subclass or singleton class.)

Oh, and khelll (:-) would probably like me to say that there is quite possibly a way for you to do what you want in a functional style. That is, by creating new objects rather than by modifying the old ones.

How to modify a matrix (Ruby std-lib Matrix class)?

You can open the class and def your own method to do this:

class Matrix
def []=(i, j, x)
@rows[i][j] = x
end
end

Ruby core Matrix vs NArray's NMatrix

Just stumbling on this question now... It's been 7 months since you've asked, so I'm sure you've found your answer by now.

However, please find information here.

Basically, the author of the core Matrix class did not add methods to perform run-time modifications to the array once it is instantiated. The NArray class allows for this.

As far as computation time, I'll leave that to somebody else, for I don't know.

Generate array of limited combinations from another array

You can use Array#permutation if you don't want repetetions in the subarrays.

  • col1 ∈ [1; 3]
  • row2 ∈ [0; 3]
days.permutation(col).to_a.slice(0, row)

Demonstration

If you want repetitions in the subarrays, you can use Array#repeated_permutation.

  • col ∈ [1; 3]
  • row ∈ [0; 33(= 27)]:
days.repeated_permutation(col).to_a.slice(0, row)

Demonstration

If you want repetitions in the subarrays and also expand your column number to the custom, independent from length of the original array number, you can use Array#repeated_combination.

  • col ∈ [1; ∞3 )
  • row ∈ [0; colcol]:
days.repeated_combination(col).to_a.slice(0, row)

Demonstration


1 col is the number of elements in each subarray.
2 row is the number of subarrays in the desired 2D array.
3 The upper bound is specified as to represent that this value is not bounded by the length of the original array.

Is there a limit on the size of an array in ruby?

There is not a software limit imposed by Ruby, but there is a limit as to how much the process can support. If you have a regular home server running the Ruby server, it would be able to handle an array until the array became too large, at which point it would begin to 'bog down', lag, crash, etc. On the other hand, if you had an extremely powerful corporate server, it could handle a much larger array, but would still eventually crash/lag if the array became too large for the process and the hardware (memory) to handle.

I don't have any concrete numbers for you, because it all depends on the hardware and software on the server.

Inspect with limited recursion

No, you might want to use either prettyprint module for a 'different' visualisation (require 'pp'; pp object) or write something yourself. To write a generic dumper is quite difficult since everyone has different needs (dump binary blobs? dump strings up to which length? dump graphs with cycles? dump up to which level? ...).

Creating array of numbers from 0 to n for positive and negative n

To support negative numbers, you could use upto and downto along with a condition:

(I'm showing a stand-alone method here instead of patching Integer)

def make_array(n)
if n > 0
0.upto(n).to_a
else
0.downto(n).to_a
end
end

The above creates an enumerator that's converted to an array using Enumerable#to_a.

You might want to skip the intermediate object (the enumerator) by directly calling Array::new - it creates an array with the given number of elements:

n = 3
Array.new(n) #=> [nil, nil, nil]

If a block is given, it passes each element's index to the block and we are supposed to returns its value. The index is in fact just what we want, so we can simply return it:

Array.new(n) { |i| i } #=> [0, 1, 2]

As you can see, Array.new(n) returns n elements, but we need n + 1, so let's fix that:

Array.new(n + 1) { |i| i } #=> [0, 1, 2, 3]

Unfortunately, Array::new doesn't accept a negative size:

Array.new(-3) #=> negative array size (ArgumentError)

So for negative n we have to pass -n and also return -i:

n = -3
Array.new(-n + 1) { |i| -i } #=> [0, -1, -2, -3]

As a method:

def make_array(n)
if n > 0
Array.new(n + 1) { |i| i }
else
Array.new(-n + 1) { |i| -i }
end
end

Let's try to avoid the duplication.

Converting n to a positive number is easy using abs:

3.abs  #=> 3
-3.abs #=> 3

Applied to our code:

n = 3
Array.new(n.abs + 1) { |i| i } #=> [0, 1, 2, 3]

n = -3
Array.new(n.abs + 1) { |i| i } #=> [0, 1, 2, 3]

For the block, we could use a ternary if:

n = 3
Array.new(n.abs + 1) { |i| n > 0 ? i : -i } #=> [0, 1, 2, 3]

n = -3
Array.new(n.abs + 1) { |i| n > 0 ? i : -i } #=> [0, -1, -2, -3]

We can even remove the condition by using the spaceship operator a <=> b. It determines whether a is less than, equal to, or greater than b by returning -1, 0 or +1, respectively.

More specifically, for Fixnum#<=>, n <=> 0 returns 1 if n is greater than 0, and -1 if n is less than 0:

3 <=> 0  #=> 1
-3 <=> 0 #=> -1

We can use <=>'s result in our block to multiply i with:

Array.new(n.abs + 1) { |i| i * (n <=> 0) }

This is equivalent to i * 1 (if n > 0) or i * -1 (if n < 0).

(There's a third return value: n <=> 0 returns 0 if n is equal to 0 but that doesn't matter, because in that case the resulting array is [0] and 0 * 0 is still 0)

As a method:

def make_array(n)
Array.new(n.abs + 1) { |i| i * (n <=> 0) }
end

Although it is short, this method became quite complex and it's not obvious what is is doing. Therefore, I would prefer the first method (the one using upto and downto) because of its simplicity.

has_many through: how to retrieve the id of a line in the correspondance table?

OK, I am stupid...

i was focusing on the lines where i know that item.matrices[x] was not nil... and the error came from the lines where items.matrices[x] is nil...

So everything is solved by just adding a unless items.matrices[x].nil?

That's the fun thing about programming: wasting time for things like this... but learning anyway :)



Related Topics



Leave a reply



Submit