1になるまで何回処理が行われるかを表示します。
C++
1#include <functional>
2#include <iostream>
3
4int main()
5{
6 std::function<int(int)> f = [&f](auto n) {
7 if (n == 1) return 0;
8 return f(n % 2 ? 3 * n + 1 : n / 2) + 1;
9 };
10
11 int i = 1;
12 std::cin >> i;
13 std::cout << f(i) << std::endl;
14 return 0;
15}
【Q&A】
Q: 課題に対してすぐにコードを与えるのは良くないという人がいます。どう思いますか?
A: ある質問の私の回答を参考にしてください。
Q: このコードはなんですか?
A: とある質問をしたときに、コラッツの計算で1になるまでをカウントするコードをたくさん書いたのでそのときのコードを引っ張ってきて、ちょっと書き換えました。
Q: 三項演算子は悪であるとか言ってませんでしたか?
A: 人は時と場合で意見が変わるものです。
Q: 偶数・奇数を調べるときは!(n % 2)
やn % 2
を条件式に入れるのではなくn % 2 == 0
やn % 2 != 0
等と書くべきであるとどこかで書いてませんでしたか?
A: ひ、人は時と場合で意見が変わるものです。
Q: 課題が「任意の整数」となっている場合、あなたはいつも「int
じゃ小さすぎるので多倍長整数使え」とか言ってませんでしたか?
A: ひ、ひと、人は時と場合で意見が変わるものですぅ。
Q: でも、零や負の数ぐらいはチェックしないのですか?
A: そもそもコラッツの予想は「任意の正の整数」に対してなのに、「任意の整数」と言っている課題がおかしいから、そこは大目に見てください。
Q: これって与えられた数値が大きすぎるとスタックオーバーフローしませんか?
A: 最適化オプションを付け忘れていなければしないはずです。綺麗な末尾再帰だし。逆アセンブルしてまでは確認してませんけど。
Q: std::function<int(int)>
は型推論できそうですが、auto
にしないのですか?
A: **できません。**できない理由はこちらの回答を参考にしてください。C++17がリリースされ、C++20ももうすぐ出そうですが、named lambdaはまだ未採用なようです。
Q: もし、コラッツの予想に反例が存在した場合、無限ループになりませんか?
A: Wikipediaによると5*2^60までは予想が成り立つことがわかっています。現在主流の環境のほとんどはint
が32bitなので、このコードではそんな大きな数は計算できないから、無限ループになることはありません(ただしint
のオーバーフローで負の値に突入し、無限ループに陥ることはあり得る)。ただ、反例が存在することを前提にするなら…どうするんでしょう?ここらへんは数論やっている数学者に聞いてください。私じゃわかりません。
Q: もっと高速にできないの?
A: Wikipediaによると方法はあるみたいです。
Q: もしかして、ここが本編?
A: お、やっと気付いたかい。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。