user8211487
user8211487

Reputation:

Recursion Multidimensional Array

So I have the task to reverse a multidimensional array recursively. I can't seem to figure out how.

I have written code that, can reverse a multidimensional array but it is not recursive. Could you guys help me make it recursive?

It should look something like this in the end:

ary = [1,[1,22,[5,7,0],8],2,3]
reverse_rek(ary)
#=> [3, 2, [1, 22, [5, 7, 0], 8], 1]

Here is my attempt:

def reverse_rek(ary)
  if not ary.is_a?(Array)
    raise ArgumentError, "Dies ist kein Array"
  end
  reverse_rek_intern(ary)  
end

def reverse_rek_intern(ary)
  len = ary.length-1
  reverse_ary =[]
    ary.each_index { |index| 
      reverse_ary[index] = ary[len-index]
    }
  return reverse_ary
end

Thank you!

Upvotes: 1

Views: 429

Answers (3)

Gerry
Gerry

Reputation: 10497

You can also use pop() along with unshift(), like this:

def reverse_rek(ary)
  if not ary.is_a?(Array)
    raise ArgumentError, "Dies ist kein Array"
  end
  reverse_rek_intern(ary)  
end

def reverse_rek_intern(ary)
  last = ary.pop
  reverse_rek_intern(ary) unless ary.empty?
  ary.unshift(last)
end

Or, combining both methods into one:

def reverse_rek(ary)
  raise ArgumentError, "Dies ist kein Array" unless ary.is_a?(Array)

  last = ary.pop
  reverse_rek_intern(ary) unless ary.empty?
  ary.unshift(last)
end

Either option will result in the desired output:

ary = [1,[1,22,[5,7,0],8],2,3]
reverse_rek(ary)
#=> [3,2,[1,22,[5,7,0],8],1]

As Peter points out in his answer, i agree that, when the received argument is not an array, its better to return the object itself instead of raising an error.

So, the above method could be updated like this:

def reverse_rek(ary)
  return ary unless ary.is_a?(Array)

  last = ary.pop
  reverse_rek_intern(ary) unless ary.empty?
  ary.unshift(last)
end

Upvotes: 0

Peter Camilleri
Peter Camilleri

Reputation: 1912

All the answers so far suffer from simulated polymorphism. Using non OO code to simulate OO behaviour. Checking to see if something is an Array is a dead give away. The following code creates a reverse_rek method for arrays and objects.

class Object
  def reverse_rek
    self
  end
end

class Array
  def reverse_rek
    reverse.map{|element| element.reverse_rek }
  end
end

Here are some examples of the code in action:

irb(main):003:0> [1,2,3].reverse_rek
=> [3, 2, 1]
irb(main):004:0> [1,[2.0,2.1,2.3],3].reverse_rek
=> [3, [2.3, 2.1, 2.0], 1]
irb(main):005:0> [1,[2.0,2.1,2.3],['a','b','c'],3].reverse_rek
=> [3, ["c", "b", "a"], [2.3, 2.1, 2.0], 1]

One difference is this code does not generate errors on non-arrays, they just return themselves. In a sense, they are treated as arrays with one element. and thus not needing to be reversed. Raising errors was not stated as a requirement.

Upvotes: 1

Aetherus
Aetherus

Reputation: 8888

An in-place version

def recursive_reverse!(thing)
  case thing
    when Array
      thing.reverse!
      thing.map!{|x| recursive_reverse! x}
    else
      thing
  end
end

The exclamation mark means it modifies the original structure.

And the safe version which doesn't modify the original array or its sub arrays at any level of depth.

def recursive_reverse(thing)
  case thing
    when Array
      thing.reverse.map{|x| recursive_reverse x}
    else
      thing
  end
end

Upvotes: 1

Related Questions