BETA

Pythonで解くQizzRuzz

投稿日:2018-10-15
最終更新:2018-10-24

この投稿に触発されて作成.

QizzRuzzのルール

数字を1からカウントしていき,以下の条件を満たすように出力する.

  • 3で割り切れる時はFizz
  • 5で割り切れる時はBuzz
  • 15で割り切れる時はFizzBuzz
  • 上記の条件以外はその数字

以上が通常のFizzBuzzで,QizzRuzzは以下の条件を追加する.

  • FizzBuzzを100回出力すると終了

実装

本稿では足りない頭でスッと思いついたPythonでのQizzRuzz実装を載せておきます.

1. リストのcountを使う

l = ['']
while(l.count('FizzBuzz') != 100):
    s = ''
    if len(l) % 3 == 0:
       s += 'Fizz'
    if len(l) % 5 == 0:
       s += 'Buzz'
    print(s) if len(s) != 0 else print(i)
    l.append(s)

メモリをドカドカ食いつつ速度が稼げないような実装ですね.
さすがにcountを連発するのは頭悪いので少し変えてみます.

2. 大量のif

i, j = 1, 0
while(j!=100):
    s = ''
    if i % 3 == 0:
       s += 'Fizz'
    if i % 5 == 0:
        s += 'Buzz'
    print(s) if len(s) != 0 else print(i)
    i += 1
    if s == 'FizzBuzz':
        j += 1

ある意味一番オーソドックスな実装です.
今度はif文が多くなってしまい不恰好です.
なかなかエレガントな実装をするのは難しいですね.

3. for文を使う

sys.maxintでマシンで使用可能な最大値を取ってきます.

import sys
j = 0
for i in range(1,sys.maxsize):
    s = ''
    if i % 3 == 0:
       s += 'Fizz'
    if i % 5 == 0:
        s += 'Buzz'
    print(s) if len(s) != 0 else print(i)
    if s == 'FizzBuzz':
        j += 1
        if j == 100:
           break

コードはすっきりしましたが,速度が気になったのでチェックしてみることにします.

速度チェック

実行環境

    Hardware Overview:

      Model Name: MacBook Air
      Model Identifier: MacBookAir7,2
      Processor Name: Intel Core i5
      Processor Speed: 1.6 GHz
      Number of Processors: 1
      Total Number of Cores: 2
      L2 Cache (per Core): 256 KB
      L3 Cache: 3 MB
      Memory: 8 GB

下準備

1., 2., 3.をそれぞれfb1, fb2, fb3としfb.pyにまとめます.
また,numを引数にとることで「numFizzBuzzが出たら終了」となるように終了条件を可変にしました.

def fb1(num):
    l = ['']
    while(l.count('FizzBuzz')!=num):
        i = len(l)
        s = ''
        if i % 3 == 0:
           s += 'Fizz'
        if i % 5 == 0:
            s += 'Buzz'
        l.append(s)

def fb2(num):
    i, j = 1, 0
    while(j!=num):
        s = ''
        if i % 3 == 0:
           s += 'Fizz'
        if i % 5 == 0:
            s += 'Buzz'
        i += 1
        if s == 'FizzBuzz':
            j += 1

def fb3(num):
    import sys
    j = 0
    for i in range(1,sys.maxsize):
        s = ''
        if i % 3 == 0:
           s += 'Fizz'
        if i % 5 == 0:
            s += 'Buzz'
        if s == 'FizzBuzz':
            j += 1
            if j == num:
               break

今回はipython%timeitを使います.
numは1000にして各実装方法の速度を測定しました(10000だと終わらなかったので).

結果

$ ipython
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 12:04:33)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from fb import *

In [2]: %timeit fb1(1000)
1.55 s ± 33.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [3]: %timeit fb2(1000)
3.65 ms ± 146 s per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [4]: %timeit fb3(1000)
2.98 ms ± 140 s per loop (mean ± std. dev. of 7 runs, 100 loops each)

結論

やっぱりcountwhile文は遅いことを再確認できました.

おまけ

可読性を犠牲にしてfb3を圧縮してみることにします.

import sys
j = 0
for i in range(1, sys.maxsize):
    s = ('Fizz' if i % 3 == 0 else '') + ('Buzz' if i % 5 == 0 else '')
    print(s) if len(s) != 0 else print(i)
    j += 1 if s == 'FizzBuzz' else 0
    if j == 100:
        break

速度は遅くなってしまいました.

$ ipython
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 12:04:33)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from fb import fb4

In [2]: %timeit fb4(1000)
3.95 ms ± 86.2 s per loop (mean ± std. dev. of 7 runs, 100 loops each)
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@Scstechrの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!