package org.trie4j.bv; import java.util.ArrayList; import java.util.List; import org.junit.Assert; import org.junit.Test; public class BytesConstantTimeSelect0SuccinctBitVectorTest extends AbstractSuccinctBitVectorTest { @Override protected SuccinctBitVector create() { return new BytesConstantTimeSelect0SuccinctBitVector(); } @Override protected SuccinctBitVector create(int initialCapacity) { return new BytesConstantTimeSelect0SuccinctBitVector(initialCapacity); } @Override protected SuccinctBitVector create(byte[] bytes, int bitsSize) { return new BytesConstantTimeSelect0SuccinctBitVector(bytes, bitsSize); } @Test public void test_bv1() throws Exception{ // B | 0 0 1 1 0 1 0 0 | 1 1 1 1 1 1 1 1 | 1 0 0 0 0 1 0 0 | 0 0 0 0 1 1 1 1 | 1 1 1 1 1 1 1 1 | 0 0 0 0 0 0 0 1 | // D | 1 0 0 0 0 | | 1 0 0 0 0 0 | 1 0 0 0 | | 1 0 0 0 0 0 0 | // C | 1 | 0 | 1 | 1 | 0 | 1 | // R | 0 | | 1 | 0 | | 1 | // S | 0 | | 1 | | | 2 | // S - Cの0の累積数を保持する // S[0] = 0 // Rが1になると、要素のコピーを追加 // // Cが0の場合末尾をincrement // Cが0から1に転じる場合、末尾をdecrement // Rは1つのブロックに付き、1度だけ1又は0になる。Cは0、0から1、1。 // Rが0の場合、して要素のコピーを追加。 String B = "00110100 11111111 10000100 00001111 11111111 00000001"; String D = "10 0 00 1000 00 1000 1000000"; String C = " 1 0 1 1 0 1"; String R = " 1 1 0 1"; int[] S = {0, 1, 2, 2}; go(B, D, C, R, S, generateSelect0Results(B)); } @Test public void test_bv2() throws Exception{ String B = "11111111 01111110"; String D = " 1 0"; String C = " 0 1"; String R = " 1"; int[] S = {1, 1}; go(B, D, C, R, S, generateSelect0Results(B)); } @Test public void test_bv3() throws Exception{ String B = "11111111 01111110 11111111 01010101"; String D = " 1 0 1 0 0 0"; String C = " 0 1 0 1"; String R = " 1 1"; int[] S = {1, 2, 2}; go(B, D, C, R, S, generateSelect0Results(B)); } @Test public void test_bv4() throws Exception{ String B = "11111111 11111111 11111111 01010101"; String D = " 1 0 0 0"; String C = " 0 0 0 1"; String R = " 1"; int[] S = {3, 3}; go(B, D, C, R, S, generateSelect0Results(B)); } @Test public void test_bv5() throws Exception{ String B = "11111111 11111111 11111111 01010101" + "11111111 11111110 00000001 11111111"; String D = " 1 0 0 0" + " 1 1000000"; String C = " 0 0 0 1" + " 0 1 1 0"; String R = " 1" + " 1 0"; int[] S = {3, 4, 5}; go(B, D, C, R, S, generateSelect0Results(B)); } @Test public void test_constSelect_1() throws Exception{ String C = "01001001 10000000 11111111 00000000 10101010"; String R = " 1 1 1 0 10000000 1 1 1 1"; int[] S = {1, 3, 5, 12, 20, 21, 22, 23, 24}; // (i + 1) + S[ rank( i + 1 ) ] BytesSuccinctBitVector bvC = new BytesSuccinctBitVector(); addFromBitString(bvC, C); BytesRank1OnlySuccinctBitVector bvR = new BytesRank1OnlySuccinctBitVector(); addFromBitString(bvR, R); for(int i = 1; i < 16; i++){ Assert.assertEquals(i + "", bvC.select1(i), i - 1 + S[bvR.rank1(i - 1) - 1]); } } @Test public void test_constSelect_2() throws Exception{ String C = " 0 0 0 1" + " 0 1 1 0"; String R = " 1" + " 1 0"; int[] S = {3, 4, 5}; BytesSuccinctBitVector bvC = new BytesSuccinctBitVector(); addFromBitString(bvC, C); BytesRank1OnlySuccinctBitVector bvR = new BytesRank1OnlySuccinctBitVector(); addFromBitString(bvR, R); for(int i = 1; i < 4; i++){ int bvResult = bvC.select1(i); int constResult = i - 1 + S[bvR.rank1(i - 1) - 1]; Assert.assertEquals(i + "", bvResult, constResult); } } @Test public void test_constSelect_3() throws Exception{ String C = " 1 0 1 1 0 1"; String R = " 1 1 0 1"; int[] S = {0, 1, 2, 2}; BytesSuccinctBitVector bvC = new BytesSuccinctBitVector(); addFromBitString(bvC, C); BytesRank1OnlySuccinctBitVector bvR = new BytesRank1OnlySuccinctBitVector(); addFromBitString(bvR, R); for(int i = 1; i < 4; i++){ int bvResult = bvC.select1(i); int rr = bvR.rank1(i - 1); int constResult = i - 1 + S[rr - 1]; // System.out.println(i + "] bv:" + bvResult + ", cs:" + constResult + ", rr:" + rr); Assert.assertEquals(i + "", bvResult, constResult); } } /* C 10110101 R 0 10 1 1 S 0,1,2,3 c.select1(i) = i - 1 + S[r.rank1(i - 1)] */ private void go(String B, String D, String C, String R, int[] S, int[] expectedSelect0Results){ BytesConstantTimeSelect0SuccinctBitVector bv = new BytesConstantTimeSelect0SuccinctBitVector(); // PreConstantTimeSelect0BytesSuccinctBitVector bv = new PreConstantTimeSelect0BytesSuccinctBitVector(); BytesSuccinctBitVector bv2 = new BytesSuccinctBitVector(); addFromBitString(bv, B); addFromBitString(bv2, B); assertBitStringEquals(D, bv.getBvD().toString()); // assertBitStringEquals(C, bv.getBsC().toString()); assertBitStringEquals(R, bv.getBvR().toString()); Assert.assertArrayEquals(S, bv.getArS()); for(int i = 0; i < expectedSelect0Results.length; i++){ Assert.assertEquals(i + "th select", expectedSelect0Results[i], bv2.select0(i)); try{ Assert.assertEquals(i + "th select", expectedSelect0Results[i], bv.select0(i)); } catch(ArrayIndexOutOfBoundsException e){ e.printStackTrace(); Assert.fail(i + "th select. "); } } } private void assertBitStringEquals(String expected, String actual){ int i = 0, ei = 0, ai = 0; while(true){ char ec = ' '; while(ec == ' ') ec = expected.charAt(ei++); char ac = ' '; while(ac == ' ') ac = actual.charAt(ai++); Assert.assertEquals(i++ + "th char.", Character.toString(ec), Character.toString(ac)); if(ei == expected.length() && ai == actual.length()) return; } } private void addFromBitString(BitVector bv, String bs){ for(char c : bs.toCharArray()){ if(c == '0') bv.append0(); else if(c == '1') bv.append1(); } } private int[] generateSelect0Results(String bs){ List<Integer> ret = new ArrayList<Integer>(); ret.add(-1); int s = 0; for(char c : bs.toCharArray()){ if(c == '0'){ ret.add(s++); } else if(c == '1'){ s++; } } int[] r = new int[ret.size()]; for(int i = 0;i < ret.size(); i++){ r[i] = ret.get(i); } return r; } }