是否可以仅使用2个支票来编写fizzbuzz?

时间:2013-07-06 12:23:54

标签: algorithm

显而易见的解决方案是:

if (x % 15 == 0) println("fizzbuzz");
else if (x % 3 == 0) println ("fizz");
else if (x % 5 == 0) println ("buzz");

然后你可以说诀窍就是连接嘶嘶声和嗡嗡声:

if (x % 3 == 0) print("fizz");
if (x % 5 == 0) print("buzz");
if (x % 15 == 0) println();

print("%s%s%s", x % 3 == 0 ? "fizz" : "", x % 5 == 0 ? "buzz" : "", x % 15 == 0 ? "\r\n" : "");

所以问题在于换行,​​在上述所有情况下,我们都会进行3次检查。

假设在“fizz”或“buzz”之后需要换行,如何只使用2次检查才能完成?

5 个答案:

答案 0 :(得分:21)

没有支票怎么样?

string[] output = { "fizzbuzz", "", "", "fizz", "", "buzz", "fizz", "", "", "fizz", "buzz", "", "fizz", "", "" };
print("%s", output[x % 15]);

请注意,这当然只会从代码中删除if个语句。底层代码很可能包含一两个跳转指令。

如果你想让它更清楚一些,你可以创建两个数组:

string[] fizz = { "fizz", "", "" };
string[] buzz = { "buzz", "", "", "", "" };
print("%s%s", fizz[x % 3], buzz[x % 5]);

请注意,这两个实现都不会处理负数,这是一个版本:

string[] fizz = { "fizz", "", "" };
string[] buzz = { "buzz", "", "", "", "" };
print("%s%s", fizz[((x % 3) + 3) % 3], buzz[((x % 5) + 5) % 5]);

请注意,我已经巧妙地跳过了您在代码中添加的换行符。如果你想要,我相信你可以弄清楚如何修改上面的代码来添加它:)

更重要的是:请注意,这实际上通过“官方”fizzbuzz测试,它只回答您的问题。

fizzbuzz测试是这样的:

  • 写出1到100之间的所有数字,除了3乘以3的数字你应该而不是数字写出“fizz”,而对于数字乘以5的数字你应该而不是数字写出“buzz”。如果一个数字是两者 3和5的倍数,请写出“fizzbuzz”而不是数字。

由于您的问题没有以任何方式处理“而非数字”部分,我的答案也没有。

所以,如果我们跳过循环通常需要“检查”的事实,我们可以在没有if语句的情况下编写整个fizzbuzz测试吗?

有点神奇,是的,我们可以,这是C#代码中的循环,您可以使用LINQPadIdeone进行验证:

void Main()
{
    string[] fizzbuzz = new[]
    {
        "fizzbuzz", "{0}", "{0}", "fizz", "{0}", "buzz", "fizz",
        "{0}", "{0}", "fizz", "buzz", "{0}", "fizz", "{0}", "{0}"
    };
    for (int index = 1; index <= 100; index++)
    {
        Debug.WriteLine(string.Format(fizzbuzz[index % 15], index));
    }
}

这里我依赖的事实是发送给string.Format的格式字符串实际上不必包含对参数的任何引用。

修改:正如评论中所述,我使用??获取"{0}"参数中的string.Format并将数组中的条目保留在null,但??确实是伪装的if语句,因此将其编辑出来。

答案 1 :(得分:1)

“只有两个检查”可能的目的是,如果一个数字可以除以3和5,这意味着该数字可以除以15.

利用该示例代码(仅使用一次检查):

var words = ["fizzbuzz", "buzz", "fizz"];
var index = Math.min(x % 3, 1) + Math.min(x % 5, 1) * 2;
if (index < words.length) println(words[index]);

请注意,Lasse的“如何不检查”答案仍会打印出空字符串,这似乎与原始代码不同,也是问题中陈述的主要问题之一。

如果可以在文本中包含换行符而不是使用println(),则无需检查即可完成工作:

print(["fizzbuzz\n", "buzz\n", "fizz\n", ""]
         [Math.min(x % 3, 1) + Math.min(x % 5, 1) * 2]);

P.S。

由于您要求进行两项检查:

print(["fizzbuzz\n", "buzz\n", "fizz\n", ""]
         [(x % 3 == 0 ? 0 : 1) + (x % 5 == 0 ? 0 : 2)]);

P.P.S。:

完整FizzBu​​zz的jsfiddle(包括打印号码):http://jsfiddle.net/QxDfh/

答案 2 :(得分:1)

有点代码,但它有效

for x in range(1,101):print"Fizz"[x%3*4:]+"Buzz"[x%5*4:]or x

来源:http://maxburstein.com/blog/python-shortcuts-for-the-python-beginner/

答案 3 :(得分:1)

这是一个没有用c写的任何条件表达式的解决方案。 (短缺评估除外)

#include <stdio.h>
int fizzbuzz(int i)
{
    const char* f[]={"%i\n","fizz\n","buzz\n","fizbuzz\n"};
    return i&&fizzbuzz(i-1)&&printf(f[!(i%3)|!(i%5)*2],i)||1;
}
int main()
{
    return fizzbuzz(100); 
}

答案 4 :(得分:0)

当我做FizzBu​​zz时,这就是我想做的事情,这就是我想出的:

        string[] p = { "", "Fizz", "Buzz", "FizzBuzz" };
        int n = 0;
        for (int i = 1; i <= 100; i++)
        {
            p[0] = i.ToString();
            if (i % 3 == 0)
                n += 1;
            if (i % 5 == 0)
                n += 2;
            Console.WriteLine(p[n]);
            n = 0;
        }

我的想法是在阵列中打印正确的字符串,为Fizz添加1,为Buzz添加2,如果两者都正确,则在阵列中输入FizzBu​​zz。这样,单词可以是任何东西,而不仅仅是前两个单词的组合。假设您想要Fizz,Buzz和FizzieBuzzie它只需更改数组中的[3]即可。此外,每次通过循环时,我将[0]更改为当前数字,如果没有添加任何内容,则会打印出来。

我在这里写了一篇关于我的思考过程的更深入的博客文章:

http://tomasforsman.com/blog/2018/04/19/fizzbuzz-challenge-in-c/