Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract items between 2 numbers in Ruby

Tags:

algorithm

ruby

Problem:

  • Given an array of numbers in Ruby, return the groups of numbers that appear between 1 and 2.
  • The numbers 1 and 2 do not appear in between other 1's and 2's (there are no subsets of subsets).

Example 1

input: [1, 3, 2, 1, 4, 2]

output: [[1, 3, 2], [1, 4, 2]]

Example 2

input: [0, 1, 3, 2, 10, 1, 5, 6, 7, 8, 7, 5, 2, 3, 1, -400, 2, 12, 16]

output: [ [1, 3, 2], [1, 5, 6, 7, 8, 7, 5, 2], [1, -400, 2] ]

My hunch is to use a combination of #chunk and #drop_while or a generator.

Thanks in advance.

like image 712
David Milanese Avatar asked Aug 26 '26 13:08

David Milanese


2 Answers

This is an option using [Enumerable#slice_when][1]:

ary1 = [1, 3, 2, 1, 4, 2]
ary2 = [0, 1, 3, 2, 10, 1, 5, 6, 7, 8, 7, 5, 2, 3, 1, -400, 2, 12, 16]

For example:

stop = [1, 2]
ary2.slice_when{ |e| stop.include? e }
    .each_slice(2).map { |a, b| b.unshift(a.last) if b }
    .reject { |e| e.nil? || (e.intersection stop).empty? }

#=> [[1, 3, 2], [1, 5, 6, 7, 8, 7, 5, 2], [1, -400, 2]]

Other option

More verbose but clearer, given the input:

input =  %w(b a b c a b c a c b c a c a)
start = 'a'
stop  = 'b'

Using Enumerable#each_with_object, why not use the good old if then else?:

tmp = []
pickup = false
input.each_with_object([]) do |e, res|
  if e == start
    pickup = true
    tmp << e
  elsif pickup && e == stop
    tmp << e
    res << tmp
    tmp = []
    pickup = false
  elsif pickup
    tmp << e
  end
end

#=> [["a", "b"], ["a", "b"], ["a", "c", "b"]]

  [1]: https://ruby-doc.org/core-2.7.0/Enumerable.html#method-i-slice_when
like image 111
iGian Avatar answered Aug 28 '26 10:08

iGian


Sounds like an interview question. I'll explain the simplest algorithm I can think of:

You loop through the array once and build the output as you go. When you encounter 1, you store it and the subsequent numbers into another temporary array. When you encounter 2, you put the array in the output array. The edge cases are:

  • another 1 after you start building the temporary array
  • a 2 when you don't have a temporary array

First case is easy, always build a new temp array when you encounter a 1. For the second one, you have to check whether you have any items in your temporary array and only append the temp array to your output if it's not empty.

That should get you started.

like image 22
Teoulas Avatar answered Aug 28 '26 09:08

Teoulas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!