3

I can't seem to find an algorithm to compute the number of arrays within an array. Example

Given

[ [ "Array", "1" ], [ "Array", "2" ] ]

Output should be two

Given

[
    [
        [ ["Array", "1"], ["Array", "2"] ],
        [ ["Array", "3"], ["Array", "4"] ],
    ],
    [
        [ ["Array", "5"], ["Array", "6"] ],
        [ ["Array", "7"], ["Array", "8"] ]
    ]
]`

Output should be 8

DIF
  • 2,470
  • 6
  • 35
  • 49
Miles
  • 189
  • 2
  • 13

3 Answers3

5

This recursive function will do the job for arrays of any nesting:

def count_subarrays array
  return 0 unless array && array.is_a?(Array)

  nested = array.select { |e| e.is_a?(Array) }
  if nested.empty?
    1 # this is a leaf
  else
    nested.inject(0) { |sum, ary| sum + count_subarrays(ary) }
  end
end
Aliaksei Kliuchnikau
  • 13,589
  • 4
  • 59
  • 72
0

I suggest that you use a recursion function which would return 1 if the argument is a leaf array, for example: (if there are two children in each array as in the saas course exercise)

 def array?(entity)
    entity[0].kind_of?(Array) ? array?(entity[0]) + array?(entity[1]) : 1
 end
Sergey
  • 11,548
  • 24
  • 76
  • 113
  • 1
    Your choice for a method name is quite questionable, especially so since it ends in `?` (which typically would imply it returns a boolean) yet returns a number. – Andrew Marshall Mar 05 '12 at 08:32
  • Further, this doesn't account for the case where there are anything other than exactly two elements that are both arrays, or the first element is not an array. – Andrew Marshall Mar 05 '12 at 08:34
0
class Array
  def deep_array_count()
    count = 0
    each{|el|
      #I could check with is_a?(Array), but with respond_to? you could use your own classes.
      if el.respond_to?(:deep_array_count)            
        count += 1 + el.deep_array_count
      end
    }
    count
  end
end

x = [
   [
     [
      ["Array", "1"], ["Array", "2"] ],
     [ ["Array", "3"], ["Array", "4"] ],
   ],
   [
     [ ["Array", "5"], ["Array", "6"] ],
     [ ["Array", "7"], ["Array", "8"] ]
   ]
  ]

 p x.deep_array_count 

The result in this example is 14, not your requested 8. I count each array.

To get the 8 you must count only arrays without another array.

class Array
  def deep_array_count()
    count = 0
    each{|el|
      #I could check with is_a?(Array), but with respond_to? you could use your own classes.
      if el.respond_to?(:deep_array_count)            
        i = el.deep_array_count
        count += i == 0 ? 1 : i #if no other array is inside, add 1
      end
    }
    count
  end
end

x = [
   [
     [
      ["Array", "1"], ["Array", "2"] ],
     [ ["Array", "3"], ["Array", "4"] ],
   ],
   [
     [ ["Array", "5"], ["Array", "6"] ],
     [ ["Array", "7"], ["Array", "8"] ]
   ]
  ]

 p x.deep_array_count 
knut
  • 27,320
  • 6
  • 84
  • 112