无条件或布尔逻辑的 Fizz Buzz
Fizz Buzz without conditionals or booleans

原始链接: https://evanhahn.com/fizz-buzz-without-conditionals-or-booleans/

这段代码解决经典的 FizzBuzz 挑战,但有一个独特的限制:不允许使用布尔值、条件语句或模式匹配。该解决方案利用 Python 的 `itertools.cycle` 创建无限循环的“Fizz”和“Buzz”序列。然后将这些序列与数字 1-100 组合,根据位置有效地分配“Fizz”或“Buzz”。 一个自定义的 `string_mask` 函数将数字(作为字符串)与生成的“Fizz”或“Buzz”字符串结合起来。这巧妙地避免了显式的条件逻辑。 然而,这种方法有一个局限性:它在数字达到 10,000 左右时会失效。随着数字的增大,在掩码过程中,数字的位数开始“泄露”到“Fizz”或“Buzz”字符串的末尾,导致输出不正确,例如“Buzz0”。作者承认这个缺陷,并寻求更可靠的替代解决方案。

一个Hacker News的讨论围绕着解决经典的FizzBuzz问题,*不使用*条件语句(if/else)或布尔逻辑。用户`unsnap_biceps`分享了一个简洁的、三行的Python解决方案,利用取模运算符(%)和终端覆盖来实现。他们的做法使用预定义的字符串列表(“fizzbuzz”、“fizz”、“buzz”等),通过`n%15`来索引并打印正确的输出,即使对于非常大的数字也能工作,避免整数溢出。 另一位用户`brudgers`开玩笑地批评*任何*FizzBuzz实现都是“糟糕的工程”,建议预先计算字符串。`stop50`简单地表示解决方案涉及使用取模或在屏蔽前添加“%3”和“%5”。 讨论强调了对常见编程挑战的创造性方法,侧重于效率和避免典型的控制流结构。
相关文章

原文

I recently learned about the Feeling of Computing podcast and listened to the latest episode. One of the hosts challenged listeners to “write Fizz Buzz with no booleans, no conditionals, no pattern matching, or other things that are like disguised booleans.”

Here’s my Python solution:

from itertools import cycle

def string_mask(a, b):
    return b + a[len(b) :]

def main():
    fizz = cycle(["", "", "Fizz"])
    buzz = cycle(["", "", "", "", "Buzz"])
    numbers = range(1, 101)
    for f, b, n in zip(fizz, buzz, numbers):
        print(string_mask(str(n), f + b))

main()

This solution is basically three things put together:

  1. Create endless cycling sequences of "", "", "fizz", "", "", "fizz", "", "", "fizz", ... and the same idea for buzz.

  2. Combine those two sequences with the numbers 1 through 100 using zip, to get the following sequence:

    ...
    ("", "", 7)
    ("", "", 8)
    ("Fizz", "", 9)
    ("", "Buzz", 10)
    ("", "", 11)
    ("Fizz", "", 12)
    ("", "", 13)
    ("", "", 14)
    ("Fizz", "Buzz", 15)
    ("", "", 16)
    ...
    
  3. Convert the number to a string, then “mask” it with any “Fizz”, “Buzz”, or “FizzBuzz” string. For example, string_mask("3", "Fizz") returns "Fizz", and string_mask("10015", "Buzz") returns "Buzz5".

    Because of this, my code breaks once you reach 10,000 because the digits start “leaking out” the end of the string. You’ll start seeing results like Buzz0 and Fizz2.

I’m sure there are better ways to do this, but that was my quick solution. How would you solve this problem?

联系我们 contact @ memedata.com