Ruby Quiz – Matricies

October 22nd, 2008 by Radar
nb = 5
distance = Array.new(nb, Array.new(nb))
k = 0
(0...nb).each do |i|
  (0...nb).each do |j|
    distance[j][i] = k +=1
  end
end

puts distance.inspect

This code should generate: [[1,6,11,16,21], [2,7,12,17,22], [3,8,13,18,23], [4,9,13,19,25], [5,10,15,20,25]]

But generates: [[5,10,15,20,25], [5,10,15,20,25], [5,10,15,20,25], [5,10,15,20,25], [5,10,15,20,25]]

I learned why today, and I wonder if anyone else knows.

4 Responses to “Ruby Quiz – Matricies”

  1. Keith Says:

    The problem isnt in the loop, its in the definition of the array. The definition of Array.new in the ruby documentation is:

    “Returns a new array. In the first form, the new array is empty. In the second it is created with size copies of obj (that is, size references to the same obj). The third form creates a copy of the array passed as a parameter (the array is generated by calling to_ary on the parameter). In the last form, an array of the given size is created. Each element in this array is calculated by passing the element‘s index to the given block and storing the return value.”

    So by doing an Array.new(5, Array.new(5)), you are essentially doing this:

    foo = Array.new(5) bar = [foo, foo, foo, foo, foo]

    So when ever you change bar[0], you are also changing bar[1], bar[2], etc. etc. because they are the same array.

    I hope I explained that correctly, anyway, I fixed it by changing the definition of distance to:

    distance = Array.new(nb).map { |o| Array.new }

    Which will create a new array with 5 new arrays inside it.

  2. Radar Says:

    Keith is correct, well done mate.

  3. Keith Says:

    Yay, I win the cheese!

  4. Andrew Grimm Says:

    I assumed that the problem must have been somewhere in the loop, rather than in the “setup” code. It’s always the unquestioned assumptions that trip me up.

Leave a Reply