Given a set of consecutive numbers from 1
to n
, I'm trying to find the number of subsets that do not contain consecutive numbers.
E.g., for the set [1, 2, 3]
, some possible subsets are [1, 2]
and [1, 3]
. The former would not be counted while the latter would be, since 1 and 3 are not consecutive numbers.
Here is what I have:
def f(n)
consecutives = Array(1..n)
stop = (n / 2.0).round
(1..stop).flat_map { |x|
consecutives.combination(x).select { |combo|
consecutive = false
combo.each_cons(2) do |l, r|
consecutive = l.next == r
break if consecutive
end
combo.length == 1 || !consecutive
}
}.size
end
It works, but I need it to work faster, under 12 seconds for n <= 75
. How do I optimize this method so I can handle high n
values no sweat?
I looked at:
- Check if array is an ordered subset
- How do I return a group of sequential numbers that might exist in an array?
- Check if an array is subset of another array in Ruby
and some others. I can't seem to find an answer.
Suggested duplicate is Count the total number of subsets that don't have consecutive elements, although that question is slightly different as I was asking for this optimization in Ruby and I do not want the empty subset in my answer. That question would have been very helpful had I initially found that one though! But SergGr's answer is exactly what I was looking for.