Making an array wrap, where last index + 1 = first index

Discussion in 'Ruby' started by Shawn W_, Sep 15, 2009.

  1. Shawn W_

    Shawn W_ Guest

    I'm trying to manipulate a 2D array. I have created a method that looks
    in adjacent cells of my 2D array and returns the contents found there.
    When my method tries to look for cells to the left of the far left
    column, Ruby will naturally 'wrap around' and return the far right
    column, because array index 0 - 1 = -1, which Ruby interprets as the
    last element of an array, in this case the far right of my rectangular
    2D array. Same for beyond the top row.

    What I want to do is replicate this behaviour for looking beyond the
    bottom row and far right column. In other words, I want my 2D array to
    wrap around top and bottom, left and right (in truth I only want left
    and right to wrap, and top and bottom to be blocked, but for now I'd
    just settle for full wrap).

    What would be the easiest solution. Perhaps modification or additions to
    the Array class in my program? Perhaps some addtions to my Array2D
    class?
    --
    Posted via http://www.ruby-forum.com/.
     
    Shawn W_, Sep 15, 2009
    #1
    1. Advertising

  2. [Note: parts of this message were removed to make it a legal post.]

    Hi there!


    > What would be the easiest solution. Perhaps modification or additions to
    > the Array class in my program? Perhaps some addtions to my Array2D
    > class?
    >



    You could overload the [] method, if you're only interested in array access:

    class Array2D < Array
    def []( index )
    if index >= self.length
    #wrap around
    else
    super
    end
    end

    something like that... ;-)
    Same goes for []=

    Greetz!
     
    Fabian Streitel, Sep 15, 2009
    #2
    1. Advertising

  3. def class Array2D < Array
    def []( index )
    super [] index % self.length
    end
    end

    How about that?
    --
    Posted via http://www.ruby-forum.com/.
     
    Aldric Giacomoni, Sep 15, 2009
    #3
  4. 2009/9/15 Aldric Giacomoni <>:
    > def class Array2D < Array
    > =A0def []( index )
    > =A0 =A0super [] index % self.length
    > =A0end
    > end
    >
    > How about that?


    10:16:29 c$ ruby -c <<EOF
    > def class Array2D < Array
    > def []( index )
    > super [] index % self.length
    > end
    > end
    > EOF

    -:1: formal argument cannot be a constant
    def class Array2D < Array
    ^
    -:1: syntax error, unexpected '<', expecting '\n' or ';'
    def class Array2D < Array
    ^
    -:3: syntax error, unexpected tIDENTIFIER, expecting kEND
    super [] index % self.length
    ^
    -:5: syntax error, unexpected kEND, expecting $end
    10:16:35 c$

    Rather

    10:18:27 c$ ruby19 <<EOF
    > class ArrayWrap < Array
    > def []( index )
    > super(index % length)
    > end
    > end
    > a =3D ArrayWrap.new(5) {|i| i}
    > 7.times do |i|
    > printf "%2d %2d\n", i, a
    > end
    > EOF

    0 0
    1 1
    2 2
    3 3
    4 4
    5 0
    6 1
    10:19:08 c$

    Cheers

    robert

    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Sep 16, 2009
    #4
  5. Shawn W_

    Shawn W_ Guest

    Aldric Giacomoni wrote:
    > def class Array2D < Array
    > def []( index )
    > super [] index % self.length
    > end
    > end
    >
    > How about that?


    I thought there might be a neat mathematical way to do this but never
    would have found it by myself. Finding the remainder (% in Ruby) of:

    array index / array size

    works nicely.

    I couldn't plug that code directly into my program and make it work, but
    I used the % technique. In my case it's a 2D array. I'm using the code
    by James Gray from the thread
    http://www.ruby-forum.com/topic/77572#850992, namely:

    01 class Array2D
    02
    03 def initialize(width, height)
    04 @data = Array.new(width) { Array.new(height) }
    05 end
    06
    07 def [](x, y)
    08 @data[x][y]
    09 end
    10
    11 def []=(x, y, value)
    12 @data[x][y] = value
    13 end
    14
    15 end

    I modified it to incorporate 'wrapping' like so:

    01 class Array2D
    02
    03 attr_accessor :width, :height
    04
    05 def initialize(width, height)
    06 @width = width
    07 @height = height
    08 @data = Array.new(@width) { Array.new(@height) }
    09 end
    10
    11 def [](x, y)
    12 x = x % @width
    13 y = y % @height
    14 @data[x][y]
    15 end
    16
    17 def []=(x, y, value)
    18 x = x % @width
    19 y = y % @height
    20 @data[x][y] = value
    21 end
    22
    23 end

    I'm not sure how impressed Rubyists would be with the neatness of this
    solution but it works.

    Thx very much.
    --
    Posted via http://www.ruby-forum.com/.
     
    Shawn W_, Sep 16, 2009
    #5
  6. Well, as pointed out, I'm an idiot and wrote "def class" .. It should
    just be "class" on the first line :)

    Glad to be of help.
    --
    Posted via http://www.ruby-forum.com/.
     
    Aldric Giacomoni, Sep 16, 2009
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Evan
    Replies:
    6
    Views:
    304
  2. Aaron Fude

    To wrap or not to wrap?

    Aaron Fude, May 8, 2008, in forum: Java
    Replies:
    12
    Views:
    700
    Chronic Philharmonic
    May 10, 2008
  3. Robert Klemme
    Replies:
    35
    Views:
    318
    Robert Klemme
    Dec 31, 2007
  4. Art Werschulz

    Text::Wrap::wrap difference

    Art Werschulz, Sep 22, 2003, in forum: Perl Misc
    Replies:
    0
    Views:
    232
    Art Werschulz
    Sep 22, 2003
  5. Art Werschulz

    Text::Wrap::wrap difference

    Art Werschulz, Sep 24, 2003, in forum: Perl Misc
    Replies:
    1
    Views:
    247
    Anno Siegel
    Sep 25, 2003
Loading...

Share This Page