编程语言
首页 > 编程语言> > Python中基于十六进制的FizzBu​​zz

Python中基于十六进制的FizzBu​​zz

作者:互联网

我相信对于大多数人来说,您应该熟悉FizzBu​​zz是什么.

对于那些不知道我在这里说什么的人.这是FizzBu​​zz:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

对于大多数人来说,这可能很容易创建.

尽管在网上浏览后,我发现有些帖子在不使用模运算符的情况下受到挑战.

我发现此python代码有趣:

m = [None, "Fizz", "Buzz", "FizzBuzz"]
v = 0x30490610
for i in range(1, 101):
    j = v & 3
    print(m[j] if j else i)
    v = v >> 2 | j << 28

结果:

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz

我的问题是它是如何做到的?

我知道’v’变量包含一个十六进制值.

如何实现创建FizzBu​​zz?您将如何向总初学者解释?

解决方法:

首先,我们观察到FizzBu​​zz模式是循环的,长度为15,因为n%3 =(n 15)%3,n%5 =(n 15)%5.

n是否可以被3和/或5整除可以存储以下两个信息位:00都不表示,01表示可被3整除,10表示可以被5整除,11表示可以被3和5整除.

FizzBu​​zz的数字1到15的“答案”从右到左如下:

11 00 00 01 00 10 01 00 00 01 10 00 01 00 00.

注意,每个第三对位都设置了右位,而每个第五对位都设置了左位.最右边的对对应于数字1,最左边的对对应于数字15.也许更清楚地将左位和右位分开:

v5:    1. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0. 0.
v3:    .1 .0 .0 .1 .0 .0 .1 .0 .0 .1 .0 .0 .1 .0 .0
v5|v3: 11 00 00 01 00 10 01 00 00 01 10 00 01 00 00

如果我们将此位字符串转换为十六进制,则会从您的代码段中获得魔法常数v:0x30490610.

我们可以用表达式j = v& 2提取v的后两位. 3,因为数字3的最低两位被置位,其余的未置位. (这是Python的“按位与”运算符.)

我们可以通过将v的两个比特向右移v> 2,从而在2 * 15 = 30比特之间循环. 2,然后将另一端的两个位相加(v> 2)|. (j << 28). (这些是Python的左移和右移运算符,它们也按位方式工作.)

这样,v可以看作是包含2位元素的“队列”,每个元素对应于要处理的下一个15个数字之一的“正确FizzBu​​zz答案”.从该队列中弹出元素j后,它会被推送到另一端,因此从现在开始15次迭代就可以准备好了.

最后一件事:语法print(m [j]如果j else i)的意思是“如果j不是虚假的值,例如0,则打印m [j];否则,打印i.”由于m [1],m [2]和m [3]包含与我们的FizzBu​​zz答案的2位表示相对应的正确字符串,并且j始终在0到3的范围内,因此输出是正确的.

作为练习,尝试将v更改为0x39999999,看看是否可以解释该行为. (提示:十六进制的9是二进制的1001.)

更新:这是该程序的变体.我已经用响应的显式队列q替换了十六进制值v,并且看起来吓人的v = v>>. 2 | j<< 28已被从前面弹出并向后推的弹出框q.append(q.pop(0))取代.

q = ['', '', 'Fizz', '', 'Buzz',
     'Fizz', '', '', 'Fizz', 'Buzz',
     '', 'Fizz', '', '', 'FizzBuzz']
for i in range(1, 101):
    print(q[0] or i)
    q.append(q.pop(0))

我们还可以添加一个单独的嘶嘶声和嗡嗡声队列:

f = ['', '', 'Fizz']
b = ['', '', '', '', 'Buzz']
for i in range(1, 101):
    print((f[0] + b[0]) or i)
    f.append(f.pop(0))
    b.append(b.pop(0))

由于”是一个伪造的值,因此只要f [0]和b [0]均为空字符串,(f [0] b [0])或i都将打印整数i.

标签:fizzbuzz,python
来源: https://codeday.me/bug/20191027/1947087.html