LoginSignup
4
3

More than 5 years have passed since last update.

Inverse Fizzbuzz (FizzBuzzの逆関数)

Last updated at Posted at 2012-05-16

(追記)もっと簡潔になるように解き直しました。→ http://qiita.com/items/6a0774443413c71c09d9

問題は http://d.hatena.ne.jp/matarillo/20120515/p1

私の答えは、範囲内の解をすべてリストアップしています。

解が1つでよい場合は、offsetsと掛け合わせずに、shortestsの先頭の配列だけ返せばよいです。
そうすれば、メソッドの引数からstartとendを削除できます。

Program.cs
using System;
using System.Linq;
using E = System.Linq.Enumerable;

class Program
{
    static void Main()
    {
        var result = InverseFizzBuzz(new[] { "fizz", "fizz", "buzz" }, 1, 100);
        foreach (var a in result)
        {
            Console.WriteLine(string.Join(",", a));
        }
    }

    static Tuple<int,string>[] table = E.Zip(
        new[] { 0, 3, 5, 6, 9, 10, 12},
        new[] { "fizzbuzz", "fizz", "buzz", "fizz", "fizz", "buzz", "fizz" },
        (x, y) => Tuple.Create(x, y)).ToArray();

    static int FromIndex(int index)
    {
        return (index / 7 * 15) + table[index % 7].Item1;
    }

    static bool IsMatch(int index, string value)
    {
        return table[index % 7].Item2 == value;
    }

    static int[][] InverseFizzBuzz(string[] input, int start, int end)
    {
        var list = from index in E.Range(0, 7)
                   let indices = E.Range(index, input.Length)
                   let tuples = E.Zip(indices, input, (x, y) => Tuple.Create(x, y))
                   where tuples.All(x => IsMatch(x.Item1, x.Item2))
                   let rStart = FromIndex(tuples.First().Item1)
                   let rEnd = FromIndex(tuples.Last().Item1)
                   select E.Range(rStart, rEnd - rStart + 1).ToArray();

        var lookup = list
            .Select(x => new { Value = x, Length = x.Length })
            .ToLookup(x => x.Length)
            .OrderBy(x => x.Key);

        var shortests = (lookup.Count() > 0)
            ? lookup.First().Select(x => x.Value)
            : E.Empty<int[]>();

        var oStart = start / 15;
        var oEnd = end / 15;
        var offsets = E.Range(oStart, oEnd - oStart + 1).Select(x => x * 15);

        var withOffsets = from x in shortests
                          from y in offsets
                          where (start <= x.First() + y) && (x.Last() + y <= end)
                          select x.Select(z => y + z).ToArray();

        return withOffsets.ToArray();
    }
}
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3