Inverse FizzBuzzを解いた。

私の回りではイマイチ盛り上がってないInverse FizzBuzzですが、とりあえず解いてみたので公開しておきます。
逆FizzBuzz問題 (Inverse FizzBuzz)

@list = []
(1..15).each do |v|
  out = ""
  out += "fizz" if v % 3 == 0
  out += "buzz" if v % 5 == 0
  @list << {idx: v, value: out} if out != ""
end

def inverse(list)
  out = nil
  saved_diff = 999
  @list.each_cons(list.size).each do |v|
    if list == v.map{|x| x[:value]}
      diff = v.last[:idx] - v.first[:idx]
      if saved_diff > diff
        out = v
        saved_diff = diff
      end
    end
  end
  unless out.nil?
    puts "#{list} => #{(out.first[:idx]..out.last[:idx]).to_a}"
  end
end

inverse(["fizz"])
inverse(["buzz"])
inverse(["fizz","buzz"])
inverse(["buzz","fizz"])
inverse(["fizz","buzz","fizz"])
inverse(["fizz","fizz"])
inverse(["fizz","fizz","buzz"])

ポイント

15以降は繰り返しなので、15まででパターンマッチしなければ答えは存在しないということになる。

  • 空白は気にしない

必要なのは条件にマッチする先頭とお尻の位置。答えを見ればわかるが先頭とお尻がわかれば後はそのrangeで表現できる。

  • each_consは便利だね

まさしくこの問題のためにあるようなメソッドだ。これに出会わなければ解けなかったと思う。

間違い等ありましたらご指摘下さい。