LoginSignup
2
2

More than 5 years have passed since last update.

例外処理を使ってfizzbuzz

Last updated at Posted at 2015-02-26

とある記事を見て面白そうだったのでやってみました。

例外の遷移での特殊な所は、処理の継続?部分をスキップできるところ

個人的には例外での遷移の特殊な所は、処理の継続?の部分を捨ててexceptした所にjumpすることだと思います。

具体的には、以下の様な感じです。

try:
    print(object() + 1)
except TypeError:
    print("hai")

# hai

通常の処理ならば object() + 1 に対する継続?である print() 呼び出しをスキップすることはできないですが。エラーが発生したら例外が投げられる。例外を処理する部分(try-except)が存在したら、そこで投げられた例外をキャッチする。という仕組み担っているため、 print() 呼び出しをスキップすることができています。

例外発生が終了条件としてみても

また、iterable objectのStopIterationではないですが、例外が発生したら止まる。そういう仕様にすることでループの終了条件にすることもできそうです。

幸い、通常のfizzbuzzは「1~100」までとなっています。また100を文字列にしてその長さを取ると len("100") は3なので、3桁目の最初で例外を投げれば良いということになります。これには長さが3のリスト(xs)を作ってそれに対して xs[len(str(i))] とでもやってあげれば大丈夫そうです。

そんなわけで

何か制約を付けて書いてみた方が良い気もしましたが特に良い物を思いつきませんでした。無駄にループではなく再帰してたりしてます。

import sys

xs = ["fizz", "", ""]


def g(i, x, out):
    try:
        return out((i % 5) or "buzz")
    except TypeError:
        try:
            x = xs[i % 3] or (i % 5) / (i % 5) and i
            return out(i, int(x), out)
        except ValueError:
            try:
                x += g(i, x, lambda y: y)
            except TypeError:
                pass
        except ZeroDivisionError:
            x = "buzz"
        out(i, x, out)


try:
    g(1, None, lambda i, x, out: xs[len(str(i))][g(i + 1, sys.stdout.write("{}\n".format(x)), out)])
except IndexError:
    pass

あとは例外処理のエラーメッセージからfizzbuzzを作っても良さそうですが止めました。

2
2
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
2
2