ある晩、古いノートを偶然見つけました。そこには、誰かがあるアイデアを執拗に追い求めていたかのような、謎めいた走り書きがびっしりと書かれていました。 あるページには、一つの問いが目を引きました。すべての数は1にたどり着けるのか? それはコラッツ予想と呼ばれるものに関係していました。何十年もの間、人々を悩ませ続けてきたパズルです。
そのルールは、見かけによらず単純でした。 好きな正の整数を一つ選びます。
そして、その結果に対して同じ手順を繰り返します。これはいつまでも続きます。
興味をひかれて、試しに12を選び、その旅を始めました。
12 ➜ 6 ➜ 3 ➜ 10 ➜ 5 ➜ 16 ➜ 8 ➜ 4 ➜ 2 ➜ 1
2番目の数(6)から数えて、1にたどり着くまでに9ステップかかりました。ルールを繰り返すたびに、数は変わり続けます。 最初のうちは、この数列は予測できないように思えました。上がったり下がったり、あちこちに飛び回るのです。 しかし、この予想はこう主張しています。どんな数から始めても、必ず最後は1にたどり着く、と。
それは魅力的であると同時に、当惑させるものでもありました。 なぜ、いつもこううまくいくように見えるのでしょうか? この過程が壊れてしまい、永遠にループしたり無限のかなたへ逃げていったりするような数は存在するのでしょうか? ノートには、これを解けば何か深遠なことが明らかになるかもしれない、と示唆されていました。そしてそれを成し遂げた者には、名声と富、そして歴史に名を刻む場所が待っているのです。
正の整数が与えられたとき、コラッツ予想の規則に従って1に到達するまでにかかるステップ数を返してください。
例外を発生させる必要があることもあります。そのときは、エラーの原因が何であるかを示す意味のあるエラーメッセージを必ず含めるようにしましょう。コードが読みやすくなり、デバッグが格段に楽になります。エラーの原因が特定の型だとわかっている場合は、組み込みのエラー型のいずれかを発生させることもできますが、その場合も意味のあるメッセージを含めましょう。
コラッツ予想が扱うのは正の整数だけなので、この演習では、与えられた値が0か負の整数である場合に、raise文を使って解答の中でValueErrorを「スロー」することを求めています。raiseでexceptionを発生させ、それにメッセージを添えたときにだけ、テストは合格します。
メッセージ付きでValueErrorを発生させるには、exception型の引数としてメッセージを書きます:
# example when argument is zero or a negative integer
raise ValueError("Only positive integers are allowed")