Birthday Chocolate HACKERRANK RUBY

Viewed 80

This is the original link for the problem in hackerrank: https://www.hackerrank.com/challenges/the-birthday-bar/problem

I have been fighting with this problem in Ruby and I don't know why my counter always returns 1. This is the solution. I hope you can help me to understand what I'm making wrong.

s = [1, 2, 1, 3, 2]
d = 3
m = 2


def birthday(s, d, m)
    array = []
    cont = 0
    sum = 0
    m.times {array.push(s.shift)}
    (m-1).times do
        array.each {|i| sum = sum + i}
        if sum == d
            cont += 1 
        end
        array.shift
        array.push(s.shift)    
    end
    return cont
end

birthday(s, d, m)
1 Answers

Though the following does not answer your question directly, it is a Ruby-like way of solving the problem, especially by making use of the methods Enumerable#each_cons and Enumerable#count.

def birthday(s, d, m)
  s.each_cons(m).count { |a| a.sum == d }
end
s = [1, 2, 1, 3, 2]
d = 3
m = 2    
birthday(s, d, m)
  #=> 2 ([1, 2] and [2, ])
s = [2, 2, 1, 3, 2]
d = 4
m = 2
birthday(s, d, m)
  #=> 2 ([2, 2] and [1, 3])
s = [2, 4, 3, 2, 1, 2, 6, 1]
d = 9
m = 3
birthday(s, d, m)
  #=> 4 ([2, 4, 3], [4, 3, 2], [1, 2, 6] and [2, 6, 1])

Notice from the doc that when each_cons is used without a block it returns an enumerator:

s = [1, 2, 1, 3, 2]
d = 3
m = 2
enum = s.each_cons(m)
  #=> #<Enumerator: [1, 2, 1, 3, 2]:each_cons(2)> 

enum will generate elements and pass them to count until there are no more to generate, at which time it raises a StopIteration exception:

enum.next #=> [1, 2] 
enum.next #=> [2, 1] 
enum.next #=> [1, 3] 
enum.next #=> [3, 2] 
enum.next #=> StopIteration (iteration reached an end) <exception>

We can write1:

enum.count { |a| a.sum == d }
  #=> 2 

After enum generates the first value ([1, 2]) the block variable a is assigned its value:

a = enum.next
  #=> [1, 2]

and the block calculation is performed. As

a.sum == d
  #=> [1, 2].sum == 3 => true

the count is incremented (from zero) by one. enum then passes each of its remaining values to count and the process is repeated. When, for example, [1, 3].sum == 3 => false is executed, the count is not incremented.

1. Note that since I just stepped through all the elements of enum, enum.next would generate another StopIteration exception. To execute enum.count { |a| a.sum == d } I therefore must first redefine the enumerator (enum = s.each_cons(m)) or Enumerator#rewind it: enum.rewind.

Related