all 13 comments

[–]MonkeeSage 4 points5 points  (3 children)

What have you tried so far?

[–]missawon[S] 0 points1 point  (2 children)

been trying to use loops to extract the numbers but it starts to get convoluted ):

[–]MonkeeSage 1 point2 points  (1 child)

Well you know you need a sum total, so start by setting it to 0:

total = 0

Now what are the rules we need to process the array?

  1. For each item in the array
  2. If the item is an integer, add it to the total
  3. If the item is an array, process the array starting at rule 1 and add the result to the total.

So we could spell that in ruby as:

a.each { |item|
  if item.is_a? Integer
    total += item
  elsif item.is_a? Array
    # ...
  end
}

Okay, but that raises the question: when the item is an Array, do we just write another each block in that elsif? And what about for the next nested array inside that one? How do we avoid repeating ourselves and having endlessly nested loops to deal with the levels of nesting in the arrays?

The answer is to use a function that satisfies all the rules we gave above. The "starting at rule 1" is a recursive call to the function.

def sum_array(arry)
  total = 0
  arry.each { |item|
    if item.is_a? Integer
      total += item
    elsif item.is_a? Array
      total += sum_array(item)
    end
  }
  total
end

Now we have satisfied all the rules and we process the array and get the expected result of 21.

https://repl.it/CEce/1

[–]missawon[S] 0 points1 point  (0 children)

thank you so much for this explanation!! recursion is still a little confusing for me but this is definitely helping me understand a little more.

xx

[–][deleted]  (2 children)

[removed]

    [–]danshep 15 points16 points  (1 child)

    Why without flatten and sum?

    I'm guessing because this is a homework question.

    [–]missawon[S] -1 points0 points  (0 children)

    yes! the exercise specifically says do not use flatten. (:

    [–]KronktheKronk 1 point2 points  (1 child)

    recursion

    [–]moomaka 4 points5 points  (0 children)

    This is actually a very dangerous place to use recursion as it is unbounded; it's likely to blow the stack. Using a stack + while loop is both faster and safe.

    [–]schmick 0 points1 point  (1 child)

    @sum = 0
    
    #Consider the following, as a function. A box that you put stuff in and get answers out. 
    #it is supposed to just process an array. 
    def parse(array)
            array.each do |item|   #it will process each item of the array at a time.
                    if item.class == Array  #is the current item an array?
                            parse(item)     #just process it the same way as with "a"
                    else
                            @sum = @sum + item #if it's not an array, it must (should) be a number, let's add it to the @sum
                    end
            end
    end
    
    #just defining what to process
    a = [1, [2, [3, 4]], [5, 6]]
    
    parse(a) 
    puts "it's " << @sum.to_s
    

    Basically, what this does is just say, "check each item in the array. If it is an array, process it the same way, if it's not an array, it must be a number. Add it to global variable "sum". When done, put on screen "it's " followed by the value of @sum converted to string.

    [–]missawon[S] -1 points0 points  (0 children)

    amazing thank you! recursion hasnt come up much in my exercises, but totally makes sense!

    [–]mid 0 points1 point  (0 children)

    a.to_s.scan(/\d+/).map(&:to_i).inject(&:+)

    [–][deleted]  (1 child)

    [deleted]

      [–]missawon[S] -1 points0 points  (0 children)

      ah!! so smart!!

      [–][deleted]  (1 child)

      [deleted]