総当たりのパターンを作る
検証用のコードなんかではたまに、複数個のパラメータの設定の組み合わせを全部試すようなことをやることがあります。
例えばとあるメソッドに5個パラメータがあるとしてそれらのパラメータに値を設定する or 設定しない だけでも
2の5乗で32の組み合わせがあります。
全部の組み合わせをどうにか作成したいと思い、二進数の各桁の値で設定有無を判定するようなコードを書きました。
以下のような感じです。
public class Test { public static void main(String[] args) { final int SIZE = 5; for (int i = 0; i < Math.pow(2, SIZE); i++) { for (int j = 0; j< SIZE; j++) { int flg = (i >> j) % 2; System.out.print((flg == 0 ? "OFF" : "ON") + "\t"); } System.out.println(); } } }
値のon/offだけでなく、色々なバリエーションがある場合はこれでは難しいので、
ちょっと再帰を使ってみて、scalaで書いてみる。
要するに直積を求めるものですね。
def product[A](list:List[A]*): List[List[A]] = list match { case Seq() => List(Nil) case _ => list.head.flatMap(x => product(list.tail: _*).map(y => x :: y)) } product(List(1,2,3), List("A","B","C"), List(7,8,9)) foreach println
実はこんなことしなくても、scalaでは
for(a<-List(1,2,3);b<-List("A","B","C");c<-List(7,8,9)) yield { a::b::c::Nil }
で同じ事ができるのですが、引数を可変にしたいということでこうなりました。
なお、今回のコードは末尾再帰ではないので引数が増えると簡単にOutOfMemoryErrorが起きます。
頑張って末尾再帰にしたり、Stream使ってみたりしましたが、
何だか旨くいかなかったので、何か方法を考える。。。
FPは奥が深い。