15個の要素を0,1の組み合わせで全通り出力したい
冪集合を作るときによくやるのは、15ビットを用意。n番目の要素を集合に含むか含まないかをビットの(1,0)で表す。全パターンを得るために、15ビットの符号無し整数を、単純に2^15 - 1回カウントアップします。
2進数のインクリメント
配列A全体で15ビットの2進数を表現する。A[0]を最上位桁、A[14]を最下位桁とするなら、以下のループで1回のインクリメントをエミュレートします。
Java
1 for (int j = A.length - 1, carry = 1; j >= 0 && carry == 1; --j) {
2 int c2 = A[j] & carry;
3 A[j] ^= carry;
4 carry = c2;
5 }
インクリメントにはビット演算のAND(&)とXOR(^)を使います。carry
は桁上げ出力。1加算するためcarry
の初期値を1にしています。加算器
全パターンを作るには整数をインクリメントするのが一般的ですが、配列を使うということなので加算器をエミュレートしました。
整数のインクリメント
整数のインクリメントの例を追記しておきます。配列のサイズが31を超えることがあるでしょうから、汎用性を考慮してjava.math.BigInteger
を利用する例をあげます。意外と早いです。
Java
1import java.math.BigInteger;
2import java.util.Arrays;
3
4public class BitPattern_ {
5
6 public static void main(String[] args) {
7 bitPattern(15);
8 }
9
10 static BigInteger TWO = BigInteger.ONE.add(BigInteger.ONE);
11
12 static void bitPattern(int size) {
13 int[] A = new int[size];
14 var MAX = TWO.pow(size);
15 for (var n = BigInteger.ZERO; n.compareTo(MAX) < 0; n = n.add(BigInteger.ONE)) {
16 for (int i = 0; i < size; ++i) A[i] = (n.testBit(i)) ? 1 : 0;
17 System.out.println(Arrays.toString(A));
18 }
19 }
20
21}