Google CodeJam 2016 - Ruby - Counting Sheep
In no particular order:


I'd prefer .zero? rather than == 0
You could use a hash instead of an array and remove the need to call uniq. That method quickly gets pretty expensive, especially since you're calling it on an ever-growing array
I'd like the solve method to return either an integer or nil, instead of mixing string and number return types.


As for getting digits from a number, I'd suggest using #divmod. Coverting to a string and splitting always irks me a little, even if it is a pretty straightforward solution. But like the return type from solve, I see no reason to involve strings when trying to get numbers from a number.

Basically, you can do something like this:

require 'set'

def unique_digits(number)
  digits = Set.new
  remainder = number
  while remainder &gt; 0
    remainder, digit = remainder.divmod(10)
    digits &lt;&lt; digit
  end
  digits
end


This is using a Set (part of the stdlib) since it guarantees uniqueness - no need to call uniq on an array.

As for the core of the task:

def count_sheep(n)
  return nil if n.zero?
  digits = Set.new
  current = 0
  while digits.size &lt; 10
    current += n
    digits += unique_digits(current)
  end
  current
end


All you need then is the method to run it. I'd suggest something like:

def read_input(io)
  cases = io.gets.strip.to_i
  cases.times do |i|
    n = io.gets.strip.to_i
    puts "Case ##{i+1}: #{count_sheep(n) || "INSOMNIA"}"
  end
end


Where io is a file handle or stdin. That way you can run your script in two ways; piping things to stdin, or reading from a file. All it needs is an IO object. E.g.:

read_input(ARGV[0] ? File.open(ARGV[0]) : STDIN)


should let run either $ ruby sheep.rb &lt;file&gt; or $ cat &lt;file&gt; | ruby sheep.rb



In all:

require 'set'

def unique_digits(number)
  digits = Set.new
  remainder = number
  while remainder &gt; 0
    remainder, digit = remainder.divmod(10)
    digits &lt;&lt; digit
  end
  digits
end

def count_sheep(n)
  return nil if n.zero?
  digits = Set.new
  current = 0
  while digits.size &lt; 10
    current += n
    digits += unique_digits(current)
  end
  current
end

def read_input(io)
  cases = io.gets.strip.to_i
  cases.times do |i|
    n = io.gets.strip.to_i
    puts "Case ##{i+1}: #{count_sheep(n) || "INSOMNIA"}"
  end
end

read_input(ARGV[0] ? File.open(ARGV[0]) : STDIN)