問題は http://d.hatena.ne.jp/matarillo/20120515/p1
周期7のテーブルなんか作らなくても、1..15の範囲の中で解探索して最短のものを選べばよかったんですね。
問題文にもあるとおり、IsFizzBuzzとToFizzBuzzで数字をFizzBuzzに変換して、入力と一致しているかを確かめていっています。
Program.cs
using System;
using System.Linq;
class Program
{
static void Main()
{
WriteInverseFizzBuzz(new[] { "fizz" });
WriteInverseFizzBuzz(new[] { "buzz" });
WriteInverseFizzBuzz(new[] { "fizz", "buzz" });
WriteInverseFizzBuzz(new[] { "buzz", "fizz" });
WriteInverseFizzBuzz(new[] { "fizz", "buzz", "fizz" });
WriteInverseFizzBuzz(new[] { "fizz", "fizz" });
WriteInverseFizzBuzz(new[] { "fizz", "fizz", "buzz" });
WriteInverseFizzBuzz(new[] { "buzz", "fizz", "buzz" });
}
static void WriteInverseFizzBuzz(string[] input)
{
string input2 = string.Join(",", input);
string output2 = string.Join(",", InverseFizzBuzz(input));
Console.WriteLine("{0} -> {1}", input2, output2);
}
static bool IsFizzBuzz(int number)
{
return (number % 3 == 0 || number % 5 == 0);
}
static string ToFizzBuzz(int number)
{
bool m3 = (number % 3 == 0);
bool m5 = (number % 5 == 0);
return
(m3 && m5) ? "fizzbuzz" :
(m5) ? "buzz" :
(m3) ? "fizz" :
null;
}
static Tuple<int, int> Inverse(string[] input, int start)
{
int n = start;
foreach (string element in input)
{
while (!IsFizzBuzz(n)) n++;
if (element != ToFizzBuzz(n)) return null;
n++;
}
return Tuple.Create(start, n);
}
static int[] InverseFizzBuzz(string[] input)
{
var list = Enumerable.Range(1, 15)
.Select(x => Inverse(input, x))
.Where(x => x != null);
if (list.Count() == 0) return new int[0];
var range = list
.OrderBy(x => x.Item2 - x.Item1)
.First();
return Enumerable.Range(range.Item1, range.Item2 - range.Item1)
.ToArray();
}
}
結果
fizz -> 3
buzz -> 5
fizz,buzz -> 9,10
buzz,fizz -> 5,6
fizz,buzz,fizz -> 3,4,5,6
fizz,fizz -> 6,7,8,9
fizz,fizz,buzz -> 6,7,8,9,10
buzz,fizz,buzz ->