エレガンスからは程遠いですが..
# Inverse FizzBuzz
def fizzbuzz(n)
x = ""
x << "Fizz" if n%3 == 0
x << "Buzz" if n%5 == 0
x.empty? ? n : x
end
def map_upto(max, f)
(1..max).map { |n| f[n] }
end
def be_short(item)
case item
when 'Fizz', 'Buzz'; item.chr
when Integer; 0
else 'z'
end
end
def fizzbuzz_string(max)
map_upto(max, method(:fizzbuzz)).map { |item| be_short item }.join
end
def find_seq(*sequence)
short_seq = sequence.map { |item| be_short item }
str = fizzbuzz_string(100)
min = Float::INFINITY
pos = 0
while pos = str.index(/#{short_seq.join('\d*')}/, pos)
m = $&
if m.size < min
res = [*pos+1..pos+m.size]
min = m.size
end
pos += 1
end
res
end
find_seq('Fizz') # => [3]
find_seq('Buzz') # => [5]
find_seq('Fizz', 'Buzz') # => [9, 10]
find_seq('Buzz', 'Fizz') # => [5, 6]
find_seq('Fizz', 'Buzz', 'Fizz') # => [3, 4, 5, 6]
find_seq('Fizz', 'Fizz') # => [6, 7, 8, 9]
find_seq('Fizz', 'Fizz', 'Buzz') # => [6, 7, 8, 9, 10]
find_seq('Buzz', 'Fizz', 'Buzz') # => nil