2007年6月7日

FizzBuzz?!

今早看到一篇文章,說來應徵的 200 個工程師中有 199 個不會寫 FizzBuzz 程式。需求是這樣的:
印出 1 到 100,但如果是 3 的倍數就印 Fizz,如果是 5 的倍數就印 Buzz,如果同時是 3 和 5 的倍數就印 FizzBuzz。
簡單到近乎腦殘對吧?但好笑的是就連自認會解的 programmers 在留下的 comments 裡面自己都寫錯。最常見的解法當然是:
for i in xrange(1,101):
if i%15 == 0:
print "FizzBuzz"
elif i%3 == 0:
print "Fizz"
elif i%5 == 0:
print "Buzz"
else:
print i
然而如果要把 Fizz 改成 Bizz,我們就需要改兩個字串,那如果這兩個相距很遠或是其他甚麼原因,就容易漏掉,違反 DRY (Do Not Repeat Yourself) 原則。結果想要改進的人就修成這樣:
for num in range(1, 101):
if not num % 3:
print "bizz"
elif not num % 5:
print "buzz"
else:
print num
結果在 15 時,只會印 bizz 而印不出 buzz 就錯掉啦。目前看到我覺得最帥的寫法是:
for i in range(1, 100) :
fmt = [i, "fizz", "buzz", "fizz buzz"]
print fmt[(i % 3 == 0) + 2 * (i % 5 == 0)]
用上了 binary 的想法在裡頭,很有 fu 喔。我自己的版本是這樣:
for i in xrange(1,101):
s = []
if i%3 == 0:
s.append("Fizz")
if i%5 == 0:
s.append("Buzz")
print "".join(s) or i
但我覺得速度應該不快。Anyway 實務上我覺得最好的版本是第一版啦,重複的問題可以用常數定義的方式解掉,如下:
three = "Fizz"
five = "Buzz"

for i in xrange(1,101):
if i%15 == 0:
print "".join((three, five))
elif i%3 == 0:
print three
elif i%5 == 0:
print five
else:
print i
這樣直接列出來快而且也易懂。有沒有讀者想玩一下啊? ;-)

1 則留言 :

  1. // 容易擴充又容易瞭解,要再加入%7,%9... 都很簡單

    for (i = 1; i <= 100; i++)
    {

    show_number = true;

    if ( i % 3 == 0)
    {
    printf("Fizz");
    show_number = false;
    }

    if ( i % 5 == 0)
    {
    printf("Buzz");
    show_number = false;
    }

    /* 擴充範例
    if (i % 7 == 0)
    {
    printf("HaHa");
    show_number = false;
    }
    */

    if (show_number)
    printf("%d", i);

    putchar('\n');
    }

    回覆刪除