Skip to content

Commit a38e198

Browse files
committed
Added bmh_search and bmh_search tests
1 parent 7b8483d commit a38e198

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Algorithms implemented so far:
2323

2424
**Searching:**
2525
- Binary Search
26+
- Boyer-Moore-Horspool
2627
- Knuth-Morris-Pratt
2728
- Rabin-Karp
2829

@@ -85,7 +86,6 @@ TODO:
8586
Below is an ever changing list of things that I would like to accomplish or implement. If you feel something needs to be added simply do a pull request.
8687

8788
**Algorithms to implement:**
88-
- Boyer-Moore-Horspool
8989
- Mersenne Twister
9090
- UUID Generator
9191
- Bloom Filters

algorithms/searching/bmh_search.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""
2+
bmh_search.py
3+
4+
This module implements bmh search to find a substring in a string
5+
6+
BMH Search Overview:
7+
--------------------
8+
Uses a bad-character shift of the rightmost character of the window to
9+
compute shifts.
10+
11+
Pre: a string > substring.
12+
13+
Post: returns a list of indexes where the substring was found.
14+
15+
Time: Complexity: O( m + n), where m is the substring to be found.
16+
17+
Space: Complexity: O(m), where m is the substring to be found.
18+
19+
Psuedo Code: https://github.com/FooBarWidget/boyer-moore-horspool
20+
(converted from C++)
21+
22+
bmh_search.search(string, substring) -> list[integers]
23+
bmh_search.search(string, substring) -> list[empty]
24+
"""
25+
def search(text, pattern):
26+
m = len(pattern)
27+
n = len(text)
28+
offsets = []
29+
if m > n:
30+
return offsets
31+
bmbc = []
32+
for k in range(256):
33+
bmbc.append(m)
34+
for k in range(m - 1):
35+
bmbc[ord(pattern[k])] = m - k - 1
36+
bmbc = tuple(bmbc)
37+
k = m - 1
38+
while k < n:
39+
j = m - 1
40+
i = k
41+
while j >= 0 and text[i] == pattern[j]:
42+
j -= 1
43+
i -= 1
44+
if j == -1:
45+
offsets.append(i + 1)
46+
k += bmbc[ord(text[k])]
47+
48+
return offsets

algorithms/tests/test_searching.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
""" Unit Tests for searching """
22
import unittest
3-
from ..searching import binary_search, kmp_search, rabinkarp_search
3+
from ..searching import binary_search, kmp_search, rabinkarp_search, bmh_search
44

55

66
class TestBinarySearch(unittest.TestCase):
@@ -42,4 +42,18 @@ def test_rabinkarpsearch(self):
4242
rv1 = rabinkarp_search.search(self.string,"MNOP")
4343
rv2 = rabinkarp_search.search(self.string,"BCA")
4444
self.assertIs(rv1,12)
45-
self.assertFalse(rv2)
45+
self.assertFalse(rv2)
46+
47+
class TestBMHSearch(unittest.TestCase):
48+
"""
49+
Tests BMH search on string "ABCDE FG ABCDEABCDEF"
50+
"""
51+
52+
def test_bmhsearch(self):
53+
self.string = "ABCDE FG ABCDEABCDEF"
54+
rv1 = bmh_search.search(self.string, "ABCDEA")
55+
rv2 = bmh_search.search(self.string, "ABCDER")
56+
self.assertIs(rv1[0],9)
57+
self.assertFalse(rv2)
58+
59+

algorithms/tests/test_shuffling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ def test_knuthshuffle(self):
2222
if i == self.shuffle[i]:
2323
self.not_shuffled = self.not_shuffled + 1
2424

25-
self.assertGreater(4, self.not_shuffled)
25+
self.assertGreater(5, self.not_shuffled)

0 commit comments

Comments
 (0)