github.com/tunabay/go-bitarray@v1.3.1/bitarray_search_test.go (about)

     1  // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved.
     2  // Use of this source code is governed by the MIT license that can be found in
     3  // the LICENSE file.
     4  
     5  package bitarray_test
     6  
     7  import (
     8  	"reflect"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/tunabay/go-bitarray"
    14  )
    15  
    16  func TestBitArray_HasPrefix(t *testing.T) {
    17  	tcs := []struct {
    18  		b, p string
    19  		h    bool
    20  	}{
    21  		{"", "", true},
    22  		{"", "0", false},
    23  		{"", "1", false},
    24  		{"0", "", true},
    25  		{"1", "", true},
    26  		{"0", "00", false},
    27  		{"1", "11", false},
    28  		{"0000-0000 0000", "0000-0000 000", true},
    29  		{"0000-0000 0000", "0000-0000 0000", true},
    30  		{"0000-0000 0000", "0000-0000 0000-0", false},
    31  		{"1111-1111 1111", "1111-1111 111", true},
    32  		{"1111-1111 1111", "1111-1111 1111-1", false},
    33  		{"0111-1111 1111-1111 1111", "1111", false},
    34  		{"1000-0000 0000-0000 0000", "0000", false},
    35  		{"1111-0000 0000-0000 0000", "1111", true},
    36  		{"0000-1111 1111-1111 1111", "0000", true},
    37  		{"0000-0011 1111-1111 1111", "0000-00", true},
    38  		{"1111-1100 0000-0000 0000", "1111-11", true},
    39  		{"0000-0000 0000-1111 1111", "0000-0001", false},
    40  		{"0000-0000 0000-1111 1111", "0000-0000 0000", true},
    41  		{"1111-1111 1111-1000 0000", "1111-1111 1111", true},
    42  		// TODO: more cases
    43  	}
    44  	chk := func(ba, prefix *bitarray.BitArray, want bool) {
    45  		t.Helper()
    46  		if got := ba.HasPrefix(prefix); got != want {
    47  			t.Errorf("unexpected result: got %t, want %t", got, want)
    48  			t.Logf("target: %#b", ba)
    49  			t.Logf("prefix: %#b", prefix)
    50  		}
    51  	}
    52  	for _, tc := range tcs {
    53  		baO := bitarray.MustParse(tc.b).ZOptimize()
    54  		baE := baO.ZExpand()
    55  		preO := bitarray.MustParse(tc.p).ZOptimize()
    56  		preE := preO.ZExpand()
    57  		chk(baO, preO, tc.h)
    58  		chk(baO, preE, tc.h)
    59  		chk(baE, preO, tc.h)
    60  		chk(baE, preE, tc.h)
    61  	}
    62  
    63  	var nilba *bitarray.BitArray
    64  	zeroba := bitarray.New()
    65  	ba := bitarray.MustParse("0101")
    66  	switch {
    67  	case !nilba.HasPrefix(nil): // untyped nil
    68  		t.Error("unexpected result: got false, want true")
    69  	case !nilba.HasPrefix(nilba):
    70  		t.Error("unexpected result: got false, want true")
    71  	case !nilba.HasPrefix(zeroba):
    72  		t.Error("unexpected result: got false, want true")
    73  	case !zeroba.HasPrefix(nilba):
    74  		t.Error("unexpected result: got false, want true")
    75  	case !ba.HasPrefix(nilba):
    76  		t.Error("unexpected result: got false, want true")
    77  	case nilba.HasPrefix(ba):
    78  		t.Error("unexpected result: got true, want false")
    79  	}
    80  }
    81  
    82  func TestBitArray_HasSuffix(t *testing.T) {
    83  	tcs := []struct {
    84  		b, s string
    85  		h    bool
    86  	}{
    87  		{"", "", true},
    88  		{"", "0", false},
    89  		{"", "1", false},
    90  		{"0", "", true},
    91  		{"1", "", true},
    92  		{"0", "00", false},
    93  		{"1", "11", false},
    94  		{"0000-0000 0000", "0000-0000 000", true},
    95  		{"0000-0000 0000", "0000-0000 0000", true},
    96  		{"0000-0000 0000", "0000-0000 0000-0", false},
    97  		{"1111-1111 1111", "1111-1111 111", true},
    98  		{"1111-1111 1111", "1111-1111 1111-1", false},
    99  		{"1111-1111 1111-1111 1110", "1111", false},
   100  		{"0000-0000 0000-0000 0001", "0000", false},
   101  		{"0000-0000 0000-0000 1111", "1111", true},
   102  		{"1111-1111 1111-1111 0000", "0000", true},
   103  		{"1111-1111 1111-1100 0000", "0000-00", true},
   104  		// TODO: more cases
   105  	}
   106  	chk := func(ba, suffix *bitarray.BitArray, want bool) {
   107  		t.Helper()
   108  		if got := ba.HasSuffix(suffix); got != want {
   109  			t.Errorf("unexpected result: got %t, want %t", got, want)
   110  			t.Logf("target: %#b", ba)
   111  			t.Logf("suffix: %#b", suffix)
   112  		}
   113  	}
   114  	for _, tc := range tcs {
   115  		baO := bitarray.MustParse(tc.b).ZOptimize()
   116  		baE := baO.ZExpand()
   117  		sufO := bitarray.MustParse(tc.s).ZOptimize()
   118  		sufE := sufO.ZExpand()
   119  		chk(baO, sufO, tc.h)
   120  		chk(baO, sufE, tc.h)
   121  		chk(baE, sufO, tc.h)
   122  		chk(baE, sufE, tc.h)
   123  	}
   124  
   125  	var nilba *bitarray.BitArray
   126  	zeroba := bitarray.New()
   127  	ba := bitarray.MustParse("0101")
   128  	switch {
   129  	case !nilba.HasSuffix(nil): // untyped nil
   130  		t.Error("unexpected result: got false, want true")
   131  	case !nilba.HasSuffix(nilba):
   132  		t.Error("unexpected result: got false, want true")
   133  	case !nilba.HasSuffix(zeroba):
   134  		t.Error("unexpected result: got false, want true")
   135  	case !zeroba.HasSuffix(nilba):
   136  		t.Error("unexpected result: got false, want true")
   137  	case !ba.HasSuffix(nilba):
   138  		t.Error("unexpected result: got false, want true")
   139  	case nilba.HasSuffix(ba):
   140  		t.Error("unexpected result: got true, want false")
   141  	}
   142  }
   143  
   144  func TestBitArray_Index(t *testing.T) {
   145  	tcs := []struct {
   146  		h, n string
   147  		i    int
   148  	}{
   149  		{"", "", 0},
   150  		{"", "0", -1},
   151  		{"", "1", -1},
   152  		{"0", "", 0},
   153  		{"1", "", 0},
   154  		{"0", "00", -1},
   155  		{"1", "11", -1},
   156  		{"0000-0000 0000", "0000-0000 000", 0},
   157  		{"0000-0000 0000", "0000-0000 0000", 0},
   158  		{"0000-0000 0000", "0000-0000 0000-0", -1},
   159  		{"1111-1111 1111", "1111-1111 111", 0},
   160  		{"1111-1111 1111", "1111-1111 1111-1", -1},
   161  		{"1111-1111 1111-1111 1110", "1111", 0},
   162  		{"1000-0000 0000-0000 0001", "0000", 1},
   163  		{"0000-1111 0000-0000 1111", "1111", 4},
   164  		{"1111-1111 1111-1111 0000", "0000", 16},
   165  		{"1111-1111 1111-1100 0000", "0000-00", 14},
   166  		// TODO: more cases
   167  	}
   168  	chk := func(haystack, needle *bitarray.BitArray, want int) {
   169  		t.Helper()
   170  		if got := haystack.Index(needle); got != want {
   171  			t.Errorf("unexpected result: got %d, want %d", got, want)
   172  			t.Logf("haystack: %#b", haystack)
   173  			t.Logf("  needle: %#b", needle)
   174  		}
   175  	}
   176  	for _, tc := range tcs {
   177  		haystackO := bitarray.MustParse(tc.h).ZOptimize()
   178  		haystackE := haystackO.ZExpand()
   179  		needleO := bitarray.MustParse(tc.n).ZOptimize()
   180  		needleE := needleO.ZExpand()
   181  		chk(haystackO, needleO, tc.i)
   182  		chk(haystackO, needleE, tc.i)
   183  		chk(haystackE, needleO, tc.i)
   184  		chk(haystackE, needleE, tc.i)
   185  	}
   186  
   187  	var nilba *bitarray.BitArray
   188  	zeroba := bitarray.New()
   189  	ba := bitarray.MustParse("0101")
   190  	if got := nilba.Index(nil); got != 0 { // untyped nil
   191  		t.Errorf("unexpected result: got %d, want 0", got)
   192  	}
   193  	if got := nilba.Index(nilba); got != 0 {
   194  		t.Errorf("unexpected result: got %d, want 0", got)
   195  	}
   196  	if got := nilba.Index(zeroba); got != 0 {
   197  		t.Errorf("unexpected result: got %d, want 0", got)
   198  	}
   199  	if got := zeroba.Index(nilba); got != 0 {
   200  		t.Errorf("unexpected result: got %d, want 0", got)
   201  	}
   202  	if got := ba.Index(nilba); got != 0 {
   203  		t.Errorf("unexpected result: got %d, want 0", got)
   204  	}
   205  	if got := nilba.Index(ba); got != -1 {
   206  		t.Errorf("unexpected result: got %d, want -1", got)
   207  	}
   208  }
   209  
   210  func TestBitArray_LastIndex(t *testing.T) {
   211  	tcs := []struct {
   212  		h, n string
   213  		i    int
   214  	}{
   215  		{"", "", 0},
   216  		{"", "0", -1},
   217  		{"", "1", -1},
   218  		{"0", "", 1},
   219  		{"1", "", 1},
   220  		{"0", "00", -1},
   221  		{"1", "11", -1},
   222  		{"0000-0000 0000", "0000-0000 000", 1},
   223  		{"0000-0000 0000", "0000-0000 0000", 0},
   224  		{"0000-0000 0000", "0000-0000 0000-0", -1},
   225  		{"1111-1111 1111", "1111-1111 111", 1},
   226  		{"1111-1111 1111", "1111-1111 1111-1", -1},
   227  		{"1111-1111 1111-1111 1110", "1111", 15},
   228  		{"1000-0000 0000-0000 0001", "0000", 15},
   229  		{"0000-1111 0000-0000 1111", "1111", 16},
   230  		{"1111-1111 1111-1111 0000", "0000", 16},
   231  		{"1111-1111 1111-1100 0000", "0000-00", 14},
   232  		// TODO: more cases
   233  	}
   234  	chk := func(haystack, needle *bitarray.BitArray, want int) {
   235  		t.Helper()
   236  		if got := haystack.LastIndex(needle); got != want {
   237  			t.Errorf("unexpected result: got %d, want %d", got, want)
   238  			t.Logf("haystack: %#b", haystack)
   239  			t.Logf("  needle: %#b", needle)
   240  		}
   241  	}
   242  	for _, tc := range tcs {
   243  		haystackO := bitarray.MustParse(tc.h).ZOptimize()
   244  		haystackE := haystackO.ZExpand()
   245  		needleO := bitarray.MustParse(tc.n).ZOptimize()
   246  		needleE := needleO.ZExpand()
   247  		chk(haystackO, needleO, tc.i)
   248  		chk(haystackO, needleE, tc.i)
   249  		chk(haystackE, needleO, tc.i)
   250  		chk(haystackE, needleE, tc.i)
   251  	}
   252  
   253  	var nilba *bitarray.BitArray
   254  	zeroba := bitarray.New()
   255  	ba := bitarray.MustParse("0101")
   256  	if got := nilba.LastIndex(nil); got != 0 { // untyped nil
   257  		t.Errorf("unexpected result: got %d, want 0", got)
   258  	}
   259  	if got := nilba.LastIndex(nilba); got != 0 {
   260  		t.Errorf("unexpected result: got %d, want 0", got)
   261  	}
   262  	if got := nilba.LastIndex(zeroba); got != 0 {
   263  		t.Errorf("unexpected result: got %d, want 0", got)
   264  	}
   265  	if got := zeroba.LastIndex(nilba); got != 0 {
   266  		t.Errorf("unexpected result: got %d, want 0", got)
   267  	}
   268  	if got := ba.LastIndex(nilba); got != 4 {
   269  		t.Errorf("unexpected result: got %d, want 0", got)
   270  	}
   271  	if got := nilba.LastIndex(ba); got != -1 {
   272  		t.Errorf("unexpected result: got %d, want -1", got)
   273  	}
   274  }
   275  
   276  func TestBitArray_AllIndex(t *testing.T) {
   277  	tdt := []string{
   278  		"", "", "0",
   279  		"", "0", "",
   280  		"", "1", "",
   281  		"0", "", "0,1",
   282  		"1", "", "0,1",
   283  		"0", "00", "",
   284  		"1", "11", "",
   285  		"1010", "", "0,1,2,3,4",
   286  		"0000-0000 0000", "0000-0000 000", "0,1",
   287  		"0000-0000 0000", "0000-0000 0000", "0",
   288  		"0000-0000 0000", "0000-0000 0000-0", "",
   289  		"1111-1111 1111", "1111-1111 111", "0,1",
   290  		"1111-1111 1111", "1111-1111 1111-1", "",
   291  		"1111-1111 1011-1101 1111", "1111", "0,1,2,3,4,5,10,15,16",
   292  		"1110-0000 0000-0000 0111", "00000", "3,4,5,6,7,8,9,10,11,12",
   293  		"0000-1111 0000-0000 1111", "1111", "4,16",
   294  		"1111-1111 1111-1111 0000", "0000", "16",
   295  		"1111-1111 1111-1100 0000", "0000-00", "14",
   296  		// TODO: more cases
   297  	}
   298  	chk := func(haystack, needle *bitarray.BitArray, want []int) {
   299  		t.Helper()
   300  		if got := haystack.AllIndex(needle); !reflect.DeepEqual(got, want) {
   301  			t.Error("unexpected result:")
   302  			t.Logf("haystack: %#b", haystack)
   303  			t.Logf("  needle: %#b", needle)
   304  			t.Logf("     got: %v", got)
   305  			t.Logf("    want: %v", want)
   306  		}
   307  	}
   308  	for i := 0; i < len(tdt); i += 3 {
   309  		haystackO := bitarray.MustParse(tdt[i]).ZOptimize()
   310  		haystackE := haystackO.ZExpand()
   311  		needleO := bitarray.MustParse(tdt[i+1]).ZOptimize()
   312  		needleE := needleO.ZExpand()
   313  		wants := strings.Split(tdt[i+2], ",")
   314  		want := make([]int, 0, len(wants))
   315  		for _, ss := range wants {
   316  			if s := strings.TrimSpace(ss); s != "" {
   317  				if v, err := strconv.Atoi(s); err == nil {
   318  					want = append(want, v)
   319  				}
   320  			}
   321  		}
   322  		chk(haystackO, needleO, want)
   323  		chk(haystackO, needleE, want)
   324  		chk(haystackE, needleO, want)
   325  		chk(haystackE, needleE, want)
   326  	}
   327  
   328  	var nilba *bitarray.BitArray
   329  	zeroba := bitarray.New()
   330  	ba := bitarray.MustParse("0101")
   331  	if got := nilba.AllIndex(nil); !reflect.DeepEqual(got, []int{0}) { // untyped nil
   332  		t.Errorf("unexpected result: got %v, want [0]", got)
   333  	}
   334  	if got := nilba.AllIndex(nilba); !reflect.DeepEqual(got, []int{0}) {
   335  		t.Errorf("unexpected result: got %v, want [0]", got)
   336  	}
   337  	if got := nilba.AllIndex(zeroba); !reflect.DeepEqual(got, []int{0}) {
   338  		t.Errorf("unexpected result: got %v, want [0]", got)
   339  	}
   340  	if got := zeroba.AllIndex(nilba); !reflect.DeepEqual(got, []int{0}) {
   341  		t.Errorf("unexpected result: got %v, want [0]", got)
   342  	}
   343  	if got := ba.AllIndex(nilba); !reflect.DeepEqual(got, []int{0, 1, 2, 3, 4}) {
   344  		t.Errorf("unexpected result: got %v, want [0 1 2 3 4]", got)
   345  	}
   346  	if got := nilba.AllIndex(ba); !reflect.DeepEqual(got, []int{}) {
   347  		t.Errorf("unexpected result: got %v, want []", got)
   348  	}
   349  }