github.com/searKing/golang/go@v1.2.117/exp/slices/sort_test.go (about) 1 // Copyright 2022 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package slices_test 6 7 import ( 8 "cmp" 9 "slices" 10 "strconv" 11 "strings" 12 "testing" 13 14 math_ "github.com/searKing/golang/go/exp/math" 15 slices_ "github.com/searKing/golang/go/exp/slices" 16 ) 17 18 func TestLinearSearch(t *testing.T) { 19 str1 := []string{"foo"} 20 str2 := []string{"ab", "ca"} 21 str3 := []string{"mo", "qo", "vo"} 22 str4 := []string{"ab", "ad", "ca", "xy"} 23 24 // slice with repeating elements 25 strRepeats := []string{"ba", "ca", "da", "da", "da", "ka", "ma", "ma", "ta"} 26 27 // slice with all element equal 28 strSame := []string{"xx", "xx", "xx"} 29 30 tests := []struct { 31 data []string 32 target string 33 wantPos int 34 wantFound bool 35 }{ 36 {[]string{}, "foo", 0, false}, 37 {[]string{}, "", 0, false}, 38 39 {str1, "foo", 0, true}, 40 {str1, "bar", 0, false}, 41 {str1, "zx", 1, false}, 42 43 {str2, "aa", 0, false}, 44 {str2, "ab", 0, true}, 45 {str2, "ad", 1, false}, 46 {str2, "ca", 1, true}, 47 {str2, "ra", 2, false}, 48 49 {str3, "bb", 0, false}, 50 {str3, "mo", 0, true}, 51 {str3, "nb", 1, false}, 52 {str3, "qo", 1, true}, 53 {str3, "tr", 2, false}, 54 {str3, "vo", 2, true}, 55 {str3, "xr", 3, false}, 56 57 {str4, "aa", 0, false}, 58 {str4, "ab", 0, true}, 59 {str4, "ac", 1, false}, 60 {str4, "ad", 1, true}, 61 {str4, "ax", 2, false}, 62 {str4, "ca", 2, true}, 63 {str4, "cc", 3, false}, 64 {str4, "dd", 3, false}, 65 {str4, "xy", 3, true}, 66 {str4, "zz", 4, false}, 67 68 {strRepeats, "da", 2, true}, 69 {strRepeats, "db", 5, false}, 70 {strRepeats, "ma", 6, true}, 71 {strRepeats, "mb", 8, false}, 72 73 {strSame, "xx", 0, true}, 74 {strSame, "ab", 0, false}, 75 {strSame, "zz", 3, false}, 76 } 77 for _, tt := range tests { 78 t.Run(tt.target, func(t *testing.T) { 79 { 80 pos, found := slices_.LinearSearch(tt.data, tt.target) 81 if pos != tt.wantPos || found != tt.wantFound { 82 t.Errorf("LinearSearch got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) 83 } 84 wantPos, wantFound := slices.BinarySearch(tt.data, tt.target) 85 if pos != wantPos || found != wantFound { 86 t.Errorf("LinearSearch got (%v, %v), BinarySearch want (%v, %v)", pos, found, wantPos, wantFound) 87 } 88 } 89 90 { 91 pos, found := slices_.LinearSearchFunc(tt.data, tt.target, strings.Compare) 92 if pos != tt.wantPos || found != tt.wantFound { 93 t.Errorf("LinearSearchFunc got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) 94 } 95 wantPos, wantFound := slices.BinarySearchFunc(tt.data, tt.target, strings.Compare) 96 if pos != wantPos || found != wantFound { 97 t.Errorf("LinearSearch got (%v, %v), BinarySearchFunc want (%v, %v)", pos, found, wantPos, wantFound) 98 } 99 } 100 }) 101 } 102 } 103 104 func TestLinearSearchInts(t *testing.T) { 105 tests := []struct { 106 data []int 107 target int 108 wantPos int 109 wantFound bool 110 }{ 111 {nil, 20, 0, false}, 112 {[]int{}, 20, 0, false}, 113 {[]int{20, 20, 30, 30}, 20, 0, true}, 114 {[]int{20, 20, 30, 30}, 23, 2, false}, 115 {[]int{20, 20, 30, 30}, 30, 2, true}, 116 {[]int{20, 20, 30, 30}, 43, 4, false}, 117 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 20, 0, true}, 118 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 23, 1, false}, 119 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 43, 3, false}, 120 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 80, 6, true}, 121 } 122 for _, tt := range tests { 123 t.Run(strconv.Itoa(tt.target), func(t *testing.T) { 124 { 125 pos, found := slices_.LinearSearch(tt.data, tt.target) 126 if pos != tt.wantPos || found != tt.wantFound { 127 t.Errorf("LinearSearch got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) 128 } 129 wantPos, wantFound := slices.BinarySearch(tt.data, tt.target) 130 if pos != wantPos || found != wantFound { 131 t.Errorf("LinearSearch got (%v, %v), BinarySearch want (%v, %v)", pos, found, wantPos, wantFound) 132 } 133 } 134 135 { 136 compare := cmp.Compare[int] 137 pos, found := slices_.LinearSearchFunc(tt.data, tt.target, compare) 138 if pos != tt.wantPos || found != tt.wantFound { 139 t.Errorf("LinearSearchFunc got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) 140 } 141 wantPos, wantFound := slices.BinarySearchFunc(tt.data, tt.target, compare) 142 if pos != wantPos || found != wantFound { 143 t.Errorf("LinearSearch got (%v, %v), BinarySearchFunc want (%v, %v)", pos, found, wantPos, wantFound) 144 } 145 } 146 }) 147 } 148 } 149 150 func TestPartialSortInts(t *testing.T) { 151 tests := []struct { 152 data []int 153 k int 154 }{ 155 {nil, 3}, 156 {[]int{}, 3}, 157 {[]int{20, 20, 30, 30}, 3}, 158 {[]int{20, 30}, 3}, 159 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 3}, 160 {[]int{90, 80, 70, 60, 50, 40, 30, 20}, 3}, 161 {[]int{90, 30, 70, 40, 50, 60, 80, 20}, 3}, 162 } 163 for i, tt := range tests { 164 t.Run(strconv.Itoa(i), func(t *testing.T) { 165 { 166 data1 := slices.Clone(tt.data) 167 slices_.PartialSort(data1, tt.k) 168 if !slices_.IsPartialSorted(data1, tt.k) { 169 t.Errorf("partial sort didn't sort") 170 } 171 } 172 173 { 174 data2 := slices.Clone(tt.data) 175 slices_.PartialSortFunc(data2, tt.k, cmp.Compare[int]) 176 if !slices_.IsPartialSorted(data2, tt.k) { 177 t.Errorf("partial sort func didn't sort") 178 } 179 } 180 }) 181 } 182 } 183 184 func TestSearchMin(t *testing.T) { 185 tests := []struct { 186 data []int 187 want int 188 }{ 189 {nil, 0}, 190 {[]int{}, 0}, 191 {[]int{20, 20, 30, 30}, 0}, 192 {[]int{20, 30}, 0}, 193 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 0}, 194 {[]int{90, 80, 70, 60, 50, 40, 30, 20}, 7}, 195 {[]int{90, 30, 70, 40, 50, 60, 80, 20}, 7}, 196 {[]int{90, 30, 70, 40, 50, 60, 80, 20, 100, 30}, 7}, 197 } 198 for i, tt := range tests { 199 t.Run(strconv.Itoa(i), func(t *testing.T) { 200 { 201 got := slices_.SearchMin(tt.data) 202 if got != tt.want { 203 t.Errorf("SearchMin(%v) got (%v), want (%v)", tt.data, got, tt.want) 204 } 205 } 206 { 207 got := slices_.SearchMinFunc(tt.data, cmp.Compare[int]) 208 if got != tt.want { 209 t.Errorf("SearchMinFunc(%v, math_.Compare[int]) got (%v), want (%v)", tt.data, got, tt.want) 210 } 211 } 212 }) 213 } 214 } 215 216 func TestSearchMax(t *testing.T) { 217 tests := []struct { 218 data []int 219 want int 220 }{ 221 {nil, 0}, 222 {[]int{}, 0}, 223 {[]int{20, 20, 30, 30}, 2}, 224 {[]int{20, 30}, 1}, 225 {[]int{20, 30, 40, 50, 60, 70, 80, 90}, 7}, 226 {[]int{90, 80, 70, 60, 50, 40, 30, 20}, 0}, 227 {[]int{90, 30, 70, 40, 50, 60, 80, 20}, 0}, 228 {[]int{90, 30, 70, 40, 50, 60, 80, 20, 100, 30}, 8}, 229 } 230 for i, tt := range tests { 231 t.Run(strconv.Itoa(i), func(t *testing.T) { 232 { 233 got := slices_.SearchMax(tt.data) 234 if got != tt.want { 235 t.Errorf("SearchMax(%v) got (%v), want (%v)", tt.data, got, tt.want) 236 } 237 } 238 { 239 got := slices_.SearchMinFunc(tt.data, math_.Reverse(cmp.Compare[int])) 240 if got != tt.want { 241 t.Errorf("SearchMinFunc(%v, math_.Reverse(math_.Compare[int])) got (%v), want (%v)", tt.data, got, tt.want) 242 } 243 } 244 }) 245 } 246 }