FizzBuzz問題
FizzBuzz問題
1から100までの数を表示するプログラムを書け。
ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。
[解1]普通の方法
至って普通の方法です。
static void Main(string[] args)
{
for (int i = 1; i <= 100; i++)
if (i % 3 == 0 && i % 5 == 0)
Console.WriteLine("FizzBuzz");
else if (i % 3 == 0)
Console.WriteLine("Fizz");
else if (i % 5 == 0)
Console.WriteLine("Buzz");
else
Console.WriteLine(i);
Console.ReadLine();
}
[解2] 倍数判定法(Mathクラスで数学的に)
次は、%演算子を使わないでやってみます。
倍数判定法を使います。
ちなみに、倍数判定法には次のようなものがあります。
2の倍数…1の位が2で割り切れる数。
3の倍数…全ての位の合計が3で割り切れる。
5の倍数…1の位が5で割り切れる。
7の倍数…次のいずれかの結果が7で割り切れる数。
1.下から2桁ずつ順に、1倍、2倍、4倍、…にし、結果を足し合わせる。
2.下から1桁ずつ順に、1倍、3倍、2倍、-1倍、-3倍、-2倍、…にし、結果を足し合わせる。
3.下から3桁ずつ順に、奇数番目は足して偶数番目は引く。
11の倍数…次のいずれかの結果が11で割り切れる数。
1.下の位から奇数番目は足して偶数番目は引く。
2.下から2桁ずつ足していく。
13の倍数…次のいずれかの結果が13で割り切れる数。
1.下から1桁ずつ順に、1倍、-3倍、-4倍、-1倍、3倍、4倍、…にし、結果を足し合わせる。
2.下から3桁ずつ順に、奇数番目は足して偶数番目は引く。
static void Main(string[] args)
{
for (int i = 1; i <= 100; i++)
if (Is3NoBaisu(i) && Is5NoBaisu(i))
Console.WriteLine("FizzBuzz");
else if (Is3NoBaisu(i))
Console.WriteLine("Fizz");
else if (Is5NoBaisu(i))
Console.WriteLine("Buzz");
else
Console.WriteLine(i);
Console.ReadLine();
}
static bool Is3NoBaisu(int n)
{
int keta = (int)Math.Log10(n) + 1;
int kakuketaNoWa = 0;
for (int i = 0; i < keta; i++)
{
kakuketaNoWa += ItiNoKurai(n);
n /= 10;
}
if (kakuketaNoWa >= 10)
return Is3NoBaisu(kakuketaNoWa);
else
return kakuketaNoWa == 3 || kakuketaNoWa == 6 || kakuketaNoWa == 9;
}
static bool Is5NoBaisu(int n)
{
int itiNoKurai = ItiNoKurai(n);
return itiNoKurai == 0 || itiNoKurai == 5;
}
static int ItiNoKurai(int n)
{
int keta = (int)Math.Log10(n) + 1;
for (int i = keta; i > 1; i--)
{
int ZyuNoNZyou = (int)Math.Pow(10, i - 1);
while (n >= ZyuNoNZyou)
n -= ZyuNoNZyou;
}
return n;
}
[解3]倍数判定法(文字列変換で直観的に)
文字列変換を使ってより分かりやすく解きます。
static void Main(string[] args)
{
for (int i = 1; i <= 100; i++)
if (Is3NoBaisu2(i) && Is5NoBaisu2(i))
Console.WriteLine("FizzBuzz");
else if (Is3NoBaisu2(i))
Console.WriteLine("Fizz");
else if (Is5NoBaisu2(i))
Console.WriteLine("Buzz");
else
Console.WriteLine(i);
Console.ReadLine();
}
static bool Is3NoBaisu2(int n)
{
string ns = n.ToString();
int kakuketaNoWa = 0;
foreach (char c in ns)
kakuketaNoWa += int.Parse(c.ToString());
if (kakuketaNoWa >= 10)
return Is3NoBaisu2(kakuketaNoWa);
else
return kakuketaNoWa == 3 || kakuketaNoWa == 6 || kakuketaNoWa == 9;
}
static bool Is5NoBaisu2(int n)
{
string ns = n.ToString();
int itiNoKurai = int.Parse(ns[ns.Length - 1].ToString());
return itiNoKurai == 0 || itiNoKurai == 5;
}
[解4]最大公約数
自然数nが自然数mで割り切れるならば、nとmの最大公約数は、mであるはずです。
考え方の違いだけで、やっていることは余りを計算するのと変わりありません。
寧ろ、公約数を求める部分で1から順に余りを計算していくので、かなり非効率です。
メリットはありませんが、こんな方法もあるということで。
static void Main(string[] args)
{
for (int i = 1; i <= 100; i++)
if (Is3NoBaisu3(i) && Is5NoBaisu3(i))
Console.WriteLine("FizzBuzz");
else if (Is3NoBaisu3(i))
Console.WriteLine("Fizz");
else if (Is5NoBaisu3(i))
Console.WriteLine("Buzz");
else
Console.WriteLine(i);
Console.ReadLine();
}
static bool Is3NoBaisu3(int n)
{
return Gcd(3, n) == 3;
}
static bool Is5NoBaisu3(int n)
{
return Gcd(5, n) == 5;
}
public static int Gcd(params int[] n)
{
int gcd = 1;
for (int i = 2; i <= n.Min(); i++)
{
var q1 = from j in n select j % i == 0;
if (q1.All(x => x))
gcd = i;
}
return gcd;
}
[おまけ]拡張メソッド版
class Program
{
static void Main(string[] args)
{
foreach (var x in 100.FizzBuzz())
Console.WriteLine(x);
Console.ReadLine();
}
}
public static class Extension
{
public static IEnumerable<string> FizzBuzz(this int _i)
{
foreach (int i in Enumerable.Range(1, _i))
yield return i % 3 == 0 && i % 5 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i.ToString();
}
}
