You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Boyer-Moore/README.markdown
+61-52
Original file line number
Diff line number
Diff line change
@@ -9,14 +9,14 @@ For example:
9
9
```swift
10
10
// Input:
11
11
let s ="Hello, World"
12
-
s.indexOf("World")
12
+
s.indexOf(pattern: "World")
13
13
14
14
// Output:
15
15
<String.Index?>7
16
16
17
17
// Input:
18
18
let animals ="🐶🐔🐷🐮🐱"
19
-
animals.indexOf("🐮")
19
+
animals.indexOf(pattern: "🐮")
20
20
21
21
// Output:
22
22
<String.Index?>6
@@ -32,7 +32,7 @@ Here's how you could write it in Swift:
32
32
33
33
```swift
34
34
extensionString {
35
-
funcindexOf(pattern: String) ->String.Index? {
35
+
funcindexOf(pattern: String) ->String.Index? {
36
36
// Cache the length of the search pattern because we're going to
37
37
// use it a few times and it's expensive to calculate.
38
38
let patternLength = pattern.characters.count
@@ -42,57 +42,58 @@ extension String {
42
42
// Make the skip table. This table determines how far we skip ahead
43
43
// when a character from the pattern is found.
44
44
var skipTable = [Character:Int]()
45
-
for (i, c) in pattern.characters.enumerate() {
46
-
skipTable[c] = patternLength - i -1
45
+
for (i, c) in pattern.characters.enumerated() {
46
+
skipTable[c] = patternLength - i -1
47
47
}
48
48
49
49
// This points at the last character in the pattern.
50
-
let p = pattern.endIndex.predecessor()
50
+
let p =index(before: pattern.endIndex)
51
51
let lastChar = pattern[p]
52
52
53
53
// The pattern is scanned right-to-left, so skip ahead in the string by
54
54
// the length of the pattern. (Minus 1 because startIndex already points
55
55
// at the first character in the source string.)
56
-
var i =self.startIndex.advancedBy(patternLength -1)
56
+
var i =index(self.startIndex, offsetBy: patternLength -1)
57
57
58
-
// This is a helper function that steps backwards through both strings
58
+
// This is a helper function that steps backwards through both strings
59
59
// until we find a character that doesn’t match, or until we’ve reached
60
60
// the beginning of the pattern.
61
61
funcbackwards() ->String.Index? {
62
-
var q = p
63
-
var j = i
64
-
while q > pattern.startIndex {
65
-
j =j.predecessor()
66
-
q =q.predecessor()
67
-
ifself[j] != pattern[q] { returnnil }
68
-
}
69
-
return j
62
+
var q = p
63
+
var j = i
64
+
while q > pattern.startIndex {
65
+
j =index(before: j)
66
+
q =index(before: q)
67
+
ifself[j] != pattern[q] { returnnil }
68
+
}
69
+
return j
70
70
}
71
71
72
72
// The main loop. Keep going until the end of the string is reached.
73
73
while i <self.endIndex {
74
-
let c =self[i]
75
-
76
-
// Does the current character match the last character from the pattern?
77
-
if c == lastChar {
78
-
79
-
// There is a possible match. Do a brute-force search backwards.
80
-
iflet k =backwards() { return k }
81
-
82
-
// If no match, we can only safely skip one character ahead.
83
-
i =i.successor()
84
-
} else {
85
-
// The characters are not equal, so skip ahead. The amount to skip is
86
-
// determined by the skip table. If the character is not present in the
87
-
// pattern, we can skip ahead by the full pattern length. However, if
88
-
// the character *is* present in the pattern, there may be a match up
89
-
// ahead and we can't skip as far.
90
-
i =i.advancedBy(skipTable[c] ?? patternLength)
91
-
}
74
+
let c =self[i]
75
+
76
+
// Does the current character match the last character from the pattern?
77
+
if c == lastChar {
78
+
79
+
// There is a possible match. Do a brute-force search backwards.
80
+
iflet k =backwards() { return k }
81
+
82
+
// If no match, we can only safely skip one character ahead.
83
+
i =index(after: i)
84
+
} else {
85
+
// The characters are not equal, so skip ahead. The amount to skip is
86
+
// determined by the skip table. If the character is not present in the
87
+
// pattern, we can skip ahead by the full pattern length. However, if
88
+
// the character *is* present in the pattern, there may be a match up
89
+
// ahead and we can't skip as far.
90
+
i =index(i, offsetBy: skipTable[c] ?? patternLength)
91
+
}
92
92
}
93
93
returnnil
94
-
}
94
+
}
95
95
}
96
+
96
97
```
97
98
98
99
The algorithm works as follows. You line up the search pattern with the source string and see what character from the string matches the *last* character of the search pattern:
@@ -149,34 +150,42 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm:
This backtracks from `matrix[n+1][m+1]` (bottom-right corner) to `matrix[1][1]` (top-right corner), looking for characters that are common to both strings. It adds those characters to a new string, `lcs`.
160
160
161
161
The `charInSequence` variable is an index into the string given by `self`. Initially this points to the last character of the string. Each time we decrement `i`, we also move back `charInSequence`. When the two characters are found to be equal, we add the character at `self[charInSequence]` to the new `lcs` string. (We can't just write `self[i]` because `i` may not map to the current position inside the Swift string.)
162
162
163
-
Due to backtracking, characters are added in reverse order, so at the end of the function we call `reverse()` to put the string in the right order. (Appending new characters to the end of the string and then reversing it once is faster than always inserting the characters at the front of the string.)
163
+
Due to backtracking, characters are added in reverse order, so at the end of the function we call `reversed()` to put the string in the right order. (Appending new characters to the end of the string and then reversing it once is faster than always inserting the characters at the front of the string.)
Copy file name to clipboardExpand all lines: README.markdown
+3-2
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ The goal of this project is to **explain how algorithms work**. The focus is on
10
10
11
11
All code is compatible with **Xcode 7.3** and **Swift 2.2**. We'll keep this updated with the latest version of Swift.
12
12
13
-
This is a work in progress. More algorithms will be added soon. :-)
13
+
This is a work in progress. More algorithms will be added soon. :-)
14
14
15
15
:heart_eyes:**Suggestions and contributions are welcome!**:heart_eyes:
16
16
@@ -26,7 +26,7 @@ This is a work in progress. More algorithms will be added soon. :-)
26
26
27
27
[How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request.
28
28
29
-
[Under construction](Under Construction.markdown). Algorithms that are under construction.
29
+
[Under construction](Under Construction.markdown). Algorithms that are under construction.
30
30
31
31
## Where to start?
32
32
@@ -213,6 +213,7 @@ Other algorithm repositories:
213
213
-[@lorentey](https://github.com/lorentey/). Production-quality Swift implementations of common algorithms and data structures.
214
214
-[Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of.
215
215
-[AlgorithmVisualizer](http://jasonpark.me/AlgorithmVisualizer/). Visualize algorithms on your browser.
216
+
-[Swift Structures](https://github.com/waynewbishop/SwiftStructures) Data Structures with directions on how to use them [here](http://waynewbishop.com/swift)
0 commit comments