Home > Software design >  in an array, Count the Positives and give the Sum of Negatives in Ruby
in an array, Count the Positives and give the Sum of Negatives in Ruby

Time:10-23

The question says:

Given an array of integers.

Return an array, where the first element is the count of positives numbers and the second element is sum of negative numbers. 0 is neither positive nor negative.

If the input is an empty array or is null, return an empty array.

  def count_positives_sum_negatives(last)
     pos = []
     neg = []

     x = lst.each

      if x % 2 == 0
       pos.push x
       else neg.push x
      end
     y = pos.count
     z = neg.sum

   puts "[#{y},#{z}]"
  end

I tested with

 count_positives_sum_negatives([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15])
 #should return [10, -65] 

I am unsure why my one only gives an error message:

An error occurred while loading spec_helper.
Failure/Error: if (x % 2) == 0

NoMethodError:
  undefined method `%' for #<Enumerator: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15]:each>
# ./lib/solution.rb:7:in `count_positives_sum_negatives'
# ./lib/solution.rb:18:in `<top (required)>'
# ./spec/spec_helper.rb:1:in `require'
# ./spec/spec_helper.rb:1:in `<top (required)>'
No examples found.
No examples found.

CodePudding user response:

You also certainly meant lst.each do |x| rather than x = lst.each. You get the error you do because lst.each without a block returns an Enumerator object, and that does not respond to %.

def count_positives_sum_negatives(lst)
  pos = []
  neg = []

  lst.each do |x|
    if x % 2 == 0
      pos.push x
    else 
      neg.push x
    end
  end
  
  y = pos.count
  z = neg.sum

  puts "[#{y},#{z}]"
end

Note: x % 2 == 0 can be written as x.even?

But you're looking at evens and odds, and your description says count positives and sum negatives. You can use #positive? and #negative? for this, along with #partition.

def count_positives_sum_negatives(lst)
  pos, neg = lst.partition(&:positive?)

  y = pos.count
  z = neg.sum

  puts "[#{y},#{z}]"
end

You could also use #each_with_object to give you the info you're looking for.

def count_positives_sum_negatives(lst)
  lst.each_with_object([0, 0]) do |x, arr|
    if x.positive?
      arr[0]  = 1
    else 
      arr[1]  = x
    end
  end
end

CodePudding user response:

@Chris has given the reason for your problem.

I think I would be inclined to write it as follows.

def count_positives_sum_negatives(lst)
  non_pos = lst.reject(&:positive?)
  [lst.size - non_pos.size, non_pos.sum]
end
count_positives_sum_negatives [-1, 2, 0, 0, 1, -4, -7, 0, 6]
  #=> [3, -12]

This has the weakness that a temporary array is created (non_pos), but lst.size - non_pos.size and non_pos.sum are both relatively fast calculations, the latter because it is implemented in C. One would have to benchmark, however.

lst.reject(&:positive?) is a short form of lst.reject { |n| n.positive? ).

See Array#reject and Array#sum.

  • Related