5
0

More than 5 years have passed since last update.

複素数の指数関数でFizzBuzz

Last updated at Posted at 2017-12-17
from cmath import exp
from math import pi

fizz = 1
buzz = 1
for i in range(1, 101):
    fizz *= exp(2j*pi/3)
    buzz *= exp(2j*pi/5)
    fizz_is_1 = abs(fizz - 1) < 0.0001
    buzz_is_1 = abs(buzz - 1) < 0.0001
    if fizz_is_1 and buzz_is_1:
        print("FizzBuzz")
    elif fizz_is_1:
        print("Fizz")
    elif buzz_is_1:
        print("Buzz")
    else:
        print(i)

え? なにこれ?

$\exp(j\theta)$は、半径1の円を$\theta$回転させた座標です。
また、複素数にこれを掛けることで、さらに$\theta$回転させることができます。
今回、$\exp(\frac{2j\pi}{3})$, $\exp(\frac{2j\pi}{5})$を繰り返し掛けることで、繰り返し$\frac{2\pi}{3}$, $\frac{2\pi}{5}$ラジアンずつ回転させて、周期3および5で1に戻ってくる複素数を作って、Fizz, Buzzの判定に使っています。

なお、この方法は、計算誤差が溜まっていくため、繰り返す数が100回などではなく巨大な数だと破綻すると思われますが、100回程度なら問題ありません。
周期も3や5と、小さいので、回転角が比較的大きく、なのでabs(fizz-1) < 0.0001と、割と余裕を持って1に戻ってきているかの判定もできています。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0