1
1
package com .williamfiset .algorithms .strings ;
2
2
3
3
import static com .google .common .truth .Truth .assertThat ;
4
+ import static java .util .Objects .isNull ;
4
5
6
+ import java .util .ArrayList ;
7
+ import java .util .List ;
8
+ import java .util .Random ;
5
9
import org .junit .Before ;
6
10
import org .junit .Test ;
7
11
8
12
public class BoyerMooreStringSearchTest {
9
13
10
14
private BoyerMooreStringSearch underTest ;
15
+ private Random random ;
16
+ private final int MAX_ITERATION = 20 ;
11
17
12
18
@ Before
13
19
public void setup () {
14
20
underTest = new BoyerMooreStringSearch ();
21
+ random = new Random ();
15
22
}
16
23
17
24
@ Test
@@ -35,12 +42,78 @@ public void shouldReturnOneOccurrence() {
35
42
}
36
43
37
44
@ Test
38
- public void shouldReturnMultiplyOccurrences () {
45
+ public void shouldReturnMultipleOccurrences () {
46
+ assertThat (underTest .findOccurrences ("SAAT TE" , "TE" )).containsExactly (5 );
39
47
assertThat (
40
48
underTest .findOccurrences ("Sample text for testing the Boyer-Moore algorithm." , "te" ))
41
49
.containsExactly (7 , 16 );
42
50
assertThat (underTest .findOccurrences ("Sample text for testing the Boyer-Moore algorithm." , " " ))
43
51
.containsExactly (6 , 11 , 15 , 23 , 27 , 39 );
52
+ assertThat (underTest .findOccurrences ("AABAACAADAABAABA" , "AABA" )).containsExactly (0 , 9 , 12 );
53
+ assertThat (underTest .findOccurrences ("AAAAAAA" , "AA" )).containsExactly (0 , 1 , 2 , 3 , 4 , 5 );
54
+ }
55
+
56
+ @ Test
57
+ public void shouldReturnEmptyForPatternLengthLargerThenText () {
58
+ assertThat (underTest .findOccurrences ("This is a Test Text" , "This is a test Pattern" ))
59
+ .isEmpty ();
60
+ }
61
+
62
+ @ Test
63
+ public void shouldReturnDynamicString () {
64
+ int runLength = random .nextInt (MAX_ITERATION ) + 1 ;
65
+ for (int run = 0 ; run < runLength ; run ++) {
66
+ int upperCharText = random .nextInt (3 );
67
+ int upperCharPattern = random .nextInt (3 );
68
+ int maxLengthText =
69
+ random .nextInt (1000 ) + 100 ; // random length of the string between [100=1000]
70
+ int maxLengthPattern = random .nextInt (10 );
71
+ String text = generateRandomString (upperCharText , maxLengthText );
72
+ String pattern = generateRandomString (upperCharPattern , maxLengthPattern );
73
+ assertThat (underTest .findOccurrences (text , pattern ))
74
+ .containsExactlyElementsIn (getOccurrencesBruteForce (text , pattern ));
75
+ }
76
+ }
77
+
78
+ /**
79
+ * @param text the text being searched in
80
+ * @param pattern the pattern that needs to be searched in text
81
+ * @return a list of beginning index of text where pattern exits
82
+ */
83
+ private List <Integer > getOccurrencesBruteForce (String text , String pattern ) {
84
+ if (isNull (text )
85
+ || isNull (pattern )
86
+ || text .length () < pattern .length ()
87
+ || pattern .length () == 0 ) {
88
+ return new ArrayList <>();
89
+ }
90
+ List <Integer > occurrences = new ArrayList <>();
91
+ for (int textIndex = 0 ; textIndex < text .length () - pattern .length () + 1 ; textIndex ++) {
92
+ boolean match = true ;
93
+ for (int patIndex = 0 ; patIndex < pattern .length (); patIndex ++) {
94
+ if (text .charAt (textIndex + patIndex ) != pattern .charAt (patIndex )) {
95
+ match = false ;
96
+ break ;
97
+ }
98
+ }
99
+ if (match ) {
100
+ occurrences .add (textIndex );
101
+ }
102
+ }
103
+ return occurrences ;
104
+ }
105
+
106
+ /**
107
+ * @param upperLimitAscii Largest element in the random string
108
+ * @param length Length of the random string
109
+ * @return Returns a random string containing character between [a-z]
110
+ */
111
+ private String generateRandomString (int upperLimitAscii , int length ) {
112
+ return random
113
+ .ints ('a' , 'a' + upperLimitAscii + 1 )
114
+ .limit (length )
115
+ .collect (StringBuilder ::new , StringBuilder ::appendCodePoint , StringBuilder ::append )
116
+ .toString ();
44
117
}
45
118
46
119
// TODO(william): Add a test that compares this implementation of Boyermoore
0 commit comments