Gavin Sinclair <gsinclair / soyabean.com.au> wrote:
> Hi folks,
> 
> Matrix lacks a method to return a string like (for
> Matrix[[1,2], [3,4]]):
> 
>  1 2
>  3 4
> 
> Has anybody written such a method that they could share?

Here you go - it's two-pass, and doesn't handle complex
(collection-type) elements or >2 dimensions, but it's useful in the
common case. Insert to_a at appropriate places if you don't want to mix
Enumerable into Vector.

require 'matrix'

module Enumerable
  def map_with_index
    a = []
    each_with_index {|e, i| a << yield(e,i)}
    a
  end
  alias collect_with_index map_with_index

  def formatrow(separator, *widths)
    map_with_index {|a,i| 
      w = widths[i]
      (a.to_s).slice(0..(w-1)).ljust(w)
    }.join(separator)
  end
end

class Vector
  include Enumerable
  def each
    size.times {|i| yield @elements[i]}
  end

  def each_with_index
    size.times {|i| yield @elements[i], i}
  end
end

class Matrix
  def pp
    #calculate column sizes
    a, t = [], 0
    column_size.times {|j| 
      a << column(j).inject(0) {|max, i| 
        (t = i.to_s.length) > max ? t : max
      }
    }
    (0..(row_size - 1)).map {|i| row(i).formatrow(' ',*a)}.join("\n")
  end
end

a = Matrix[[1,2,3],[4,5,6],[10,9,7]]
print a.pp