Scenario : I want to count no. of subsets having negative numbers between two zeros. Here no. of subsets with negative numbers can be consider as travelling down the hill from sea level
Consider a array
a=[0,1,0,-1,-2,-l,0]
0 here represent sea level. Numbers between zeros are steps going up/down and is represent by positive/negative consecutive steps. You can move any steps up/down but it should come to sea level before moving up/down
If you consider
0,1,0
then it means that you moved from sea level to uphill and then again to sea level
0, 1, 0
similarly
From sea level to moving down one step, second step down, one step up and then again to sea level
0, -1, -2, -1, 0
Now considering an example.
a=[0,1,0,-1,-2,-1,0]
subset #1 = [0,1]
subset #2 = [0,-1,-2,-1,0]
Output: 1
(One time travelling below sea level)
Consider another example
b = [0,1,2,1,0,-1,-2,-1,0,1,2,1,0,-1,0]
subset #1 = [0,1,2,1,0] (moving up)
subset #2 = [0,-1,-2,-1,0] (moving down)
subset #3 = [0,1,2,1,0] (moving up)
subset #4 = [0,-1,0] (moving down)
Output: 2
(Two times travelling below sea level)
CodePudding user response:
I'm wondering if there's a reason that you couldn't just count the times that you have a zero followed by a negative number; something like:
def count_below(arr)
count = 0
arr.each_index do |i|
count = 1 if arr[i] == 0 && (arr[i 1] || 0) < 0
end
count
end
irb(main):039:0> count_below([0,1,0,-1,-2,-1,0])
=> 1
irb(main):040:0> count_below([0,1,2,1,0,-1,-2,-1,0,1,2,1,0,-1,0])
=> 2
CodePudding user response:
Option 1: Produce Desired "Output" (Number of times below "Sea Level")
Assumptions:
- We start at or above Sea Level.
Proposed Solution:
b = [0,1,2,1,0,-1,-2,-1,0,1,2,1,0,-1,0]
b.each_cons(2).count {|a,b| !a.negative? && b.negative? }
Steps:
- Create an
Enumerator
of consecutive 2 elements (b.each_cons(2)
) - Count each time the first element is not negative and the second is negative (
count {|a,b| !a.negative? && b.negative? }
)
Option 2: To produce the slices in your question the following should work
Assumptions:
- We always start at Sea Level (
0
) - One must touch Sea Level when ascending or descending (e.g.
[0,1,-1]
is considered invalid input) - The first example is incorrect and should be
[[0,1,0],[0,-1,-2,-1,0]]
Proposed Solution:
b.each_cons(2).with_object([]) do |(a,b),obj|
obj << [a] if a.zero?
obj.last << b
end
#=> [[0, 1, 2, 1, 0], [0, -1, -2, -1, 0], [0, 1, 2, 1, 0], [0, -1, 0]]
Steps:
- Create an
Enumerator
of consecutive 2 elements (b.each_cons(2)
) - Iterate with a Accumulator
Array
(with_object([])
) - Every time the first element is
0
insert a new subArray
(obj << [a] if a.zero?
) - Insert the second element into the current (last) sub
Array
(obj.last << b
) with_object
will return the accumulatorArray
as the result
You could chain methods to get the same result as Option 1 (such as count {|a| a.any?(&:negative)}
)