多重forは再帰で書ける - merom686の日記
以前も書いたが、多重ループは再帰で書ける。なかなか使う機会がなかったけど、昨日AtCoderの過去問を解いていたときに使えそうだと思った(使わなかった)。
下のソースは、N以下のすべての正整数の素因数分解を順不同で出力する。N以下の素数の数だけfor文を回したいのだが、そんな多重forは書くのが面倒だし、Nが事前にわかっていない場合はそもそも書けない。そこで再帰を使って多重ループしている。
自分は昔、オセロのソフトを作ろうとして、普通は再帰を使うところなのに、多重forで深さ固定のミニマックス法を書いたことがある。それを思えば、多重ループが再帰で書けるのは当たり前だ。
#include <iostream> #include <iomanip> #include <functional> int main() { const int N = 16; int p[] = { 2, 3, 5, 7, 11, 13 }; // N以下の素数 int c[10][2] = {}; std::function<void(int, int, int)> f = [&](int m, int k, int j) { if (j < 0) { std::cout << std::setw(3) << m << " = "; bool b = false; for (int i = k - 1; i >= 0; i--) { if (b) std::cout << " * "; else b = true; std::cout << p[c[i][0]]; if (c[i][1] > 1) std::cout << "^" << c[i][1]; } if (!b) std::cout << "1"; std::cout << std::endl; return; } for (int i = 0;; i++) { c[k][0] = j; c[k][1] = i; f(m, k + (i != 0), j - 1); m *= p[j]; if (m > N) break; } }; f(1, 0, _countof(p) - 1); return 0; } /* 出力 1 = 1 2 = 2 4 = 2^2 8 = 2^3 16 = 2^4 3 = 3 6 = 2 * 3 12 = 2^2 * 3 9 = 3^2 5 = 5 10 = 2 * 5 15 = 3 * 5 7 = 7 14 = 2 * 7 11 = 11 13 = 13 */