逆fizzbuzz

FizzBuzz問題(http://d.hatena.ne.jp/matarillo/20120515/p1)を解いた。
URL先のtrackbackを見るとオートマトン的に解けるらしい?けれどシミュレーション。

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

# inverse_fizzbuzz.rb

def inverse_fizzbuzz(arr)
    if arr.size == 0 then
        return []
    end

    front = arr.shift

    # start candidate
    sc = []

    if front == "fizz" then
        sc = [3, 6, 9, 12]
    elsif front == "buzz" then
        sc = [5, 10]
    elsif front == "fizzbuzz" then
        sc = [15]
    end

    if arr.size == 0 then
        return [sc[0]]
    end

    # simulate 
    ac = []
    sc.each do |s|
        a = []
        e = -1
        (s + 1).upto(s + 15) do |n|
            if n % 15 == 0 then
                a << "fizzbuzz"
            elsif n % 3 == 0 then
                a << "fizz"
            elsif n % 5 == 0 then
                a << "buzz"
            end
            if a.size == arr.size then
                e = n
                break
            end
        end
        # is simulated result equal to original?
        if a == arr then
            ac << [*s..e]
        end
    end

    ac = ac.sort{|lhs, rhs|
        if lhs.size != rhs.size then
            next lhs.size <=> rhs.size
        else 
            next lhs <=> rhs
        end
    }

    return ac.size == 0 ? [] : ac[0]
end

def test(i, e, a)
    print("Case #%d: " % i)
    if e == a then
        puts "OK"
    else
        puts "NG (exp) " + e.to_s + " != (act) " + a.to_s
    end
end

def main()
    test(1, [3], inverse_fizzbuzz(["fizz"]))
    test(2, [5], inverse_fizzbuzz(["buzz"]))
    test(3, [9, 10], inverse_fizzbuzz(["fizz", "buzz"]))
    test(4, [5, 6], inverse_fizzbuzz(["buzz", "fizz"]))
    test(5, [3, 4, 5, 6], inverse_fizzbuzz(["fizz", "buzz", "fizz"]))
    test(6, [6, 7, 8, 9], inverse_fizzbuzz(["fizz", "fizz"]))
    test(7, [6, 7, 8, 9, 10], inverse_fizzbuzz(["fizz", "fizz", "buzz"]))
    test(8, [], inverse_fizzbuzz(["buzz", "fizz", "buzz"]))
    test(9, [], inverse_fizzbuzz(["fizz", "fizz", "fizz"]))
    test(10, [12, 13, 14, 15], inverse_fizzbuzz(["fizz", "fizzbuzz"]))
    test(11, [15, 16, 17, 18], inverse_fizzbuzz(["fizzbuzz", "fizz"]))
    test(12, [10, 11, 12, 13, 14, 15], inverse_fizzbuzz(["buzz", "fizz", "fizzbuzz"]))
    test(13, [15, 16, 17, 18, 19, 20], inverse_fizzbuzz(["fizzbuzz", "fizz", "buzz"]))
end

if __FILE__ == $0 then
    main()
end