Skip to content

Commit 68f1dcb

Browse files
author
Chris Pilcher
authored
Merge pull request kodecocodes#243 from aquarchitect/master
Migrate LCS to Swift 3.0
2 parents e22b376 + b2c302f commit 68f1dcb

File tree

7 files changed

+77
-38
lines changed

7 files changed

+77
-38
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ script:
2626
- xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests
2727
# - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests
2828
# - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests
29-
# - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests
29+
- xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests
3030
# - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests
3131
# - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests
3232
- xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests

Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
extension String {
2-
public func longestCommonSubsequence(other: String) -> String {
2+
public func longestCommonSubsequence(_ other: String) -> String {
33

4-
func lcsLength(other: String) -> [[Int]] {
5-
var matrix = [[Int]](count: self.characters.count+1, repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0))
4+
func lcsLength(_ other: String) -> [[Int]] {
5+
var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1)
66

7-
for (i, selfChar) in self.characters.enumerate() {
8-
for (j, otherChar) in other.characters.enumerate() {
7+
for (i, selfChar) in self.characters.enumerated() {
8+
for (j, otherChar) in other.characters.enumerated() {
99
if otherChar == selfChar {
1010
matrix[i+1][j+1] = matrix[i][j] + 1
1111
} else {
@@ -16,7 +16,7 @@ extension String {
1616
return matrix
1717
}
1818

19-
func backtrack(matrix: [[Int]]) -> String {
19+
func backtrack(_ matrix: [[Int]]) -> String {
2020
var i = self.characters.count
2121
var j = other.characters.count
2222
var charInSequence = self.endIndex
@@ -28,15 +28,15 @@ extension String {
2828
j -= 1
2929
} else if matrix[i][j] == matrix[i - 1][j] {
3030
i -= 1
31-
charInSequence = charInSequence.predecessor()
31+
charInSequence = self.index(before: charInSequence)
3232
} else {
3333
i -= 1
3434
j -= 1
35-
charInSequence = charInSequence.predecessor()
35+
charInSequence = self.index(before: charInSequence)
3636
lcs.append(self[charInSequence])
3737
}
3838
}
39-
return String(lcs.characters.reverse())
39+
return String(lcs.characters.reversed())
4040
}
4141

4242
return backtrack(lcsLength(other))
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<playground version='5.0' target-platform='ios'>
2+
<playground version='5.0' target-platform='ios' executeOnSourceChanges='false'>
33
<timeline fileName='timeline.xctimeline'/>
44
</playground>

Longest Common Subsequence/LongestCommonSubsequence.swift

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
extension String {
2-
public func longestCommonSubsequence(other: String) -> String {
2+
public func longestCommonSubsequence(_ other: String) -> String {
33

44
// Computes the length of the lcs using dynamic programming.
55
// Output is a matrix of size (n+1)x(m+1), where matrix[x][y] is the length
66
// of lcs between substring (0, x-1) of self and substring (0, y-1) of other.
7-
func lcsLength(other: String) -> [[Int]] {
7+
func lcsLength(_ other: String) -> [[Int]] {
88

99
// Create matrix of size (n+1)x(m+1). The algorithm needs first row and
1010
// first column to be filled with 0.
11-
var matrix = [[Int]](count: self.characters.count+1, repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0))
11+
var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1)
1212

13-
for (i, selfChar) in self.characters.enumerate() {
14-
for (j, otherChar) in other.characters.enumerate() {
13+
for (i, selfChar) in self.characters.enumerated() {
14+
for (j, otherChar) in other.characters.enumerated() {
1515
if otherChar == selfChar {
1616
// Common char found, add 1 to highest lcs found so far.
1717
matrix[i+1][j+1] = matrix[i][j] + 1
@@ -28,7 +28,7 @@ extension String {
2828

2929
// Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are
3030
// common to both strings.
31-
func backtrack(matrix: [[Int]]) -> String {
31+
func backtrack(_ matrix: [[Int]]) -> String {
3232
var i = self.characters.count
3333
var j = other.characters.count
3434

@@ -46,21 +46,22 @@ extension String {
4646
else if matrix[i][j] == matrix[i - 1][j] {
4747
i -= 1
4848
// As i was decremented, move back charInSequence.
49-
charInSequence = charInSequence.predecessor()
49+
charInSequence = self.index(before: charInSequence)
5050
}
5151
// Value on the left and above are different than current cell.
5252
// This means 1 was added to lcs length (line 17).
5353
else {
5454
i -= 1
5555
j -= 1
56-
charInSequence = charInSequence.predecessor()
56+
charInSequence = self.index(before: charInSequence)
57+
5758
lcs.append(self[charInSequence])
5859
}
5960
}
6061

6162
// Due to backtrack, chars were added in reverse order: reverse it back.
6263
// Append and reverse is faster than inserting at index 0.
63-
return String(lcs.characters.reverse())
64+
return String(lcs.characters.reversed())
6465
}
6566

6667
// Combine dynamic programming approach with backtrack to find the lcs.

Longest Common Subsequence/README.markdown

+15-16
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ To determine the length of the LCS between all combinations of substrings of `a`
1818

1919
> **Note:** During the following explanation, `n` is the length of string `a`, and `m` is the length of string `b`.
2020
21-
To find the lengths of all possible subsequences, we use a helper function, `lcsLength()`. This creates a matrix of size `(n+1)` by `(m+1)`, where `matrix[x][y]` is the length of the LCS between the substrings `a[0...x-1]` and `b[0...y-1]`.
21+
To find the lengths of all possible subsequences, we use a helper function, `lcsLength(_:)`. This creates a matrix of size `(n+1)` by `(m+1)`, where `matrix[x][y]` is the length of the LCS between the substrings `a[0...x-1]` and `b[0...y-1]`.
2222

23-
Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength()` is the following:
23+
Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength(_:)` is the following:
2424

2525
```
2626
| | Ø | A | B | D | C | A | B |
@@ -34,16 +34,15 @@ Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength()` is th
3434

3535
In this example, if we look at `matrix[3][4]` we find the value `3`. This means the length of the LCS between `a[0...2]` and `b[0...3]`, or between `"ABC"` and `"ABDC"`, is 3. That is correct, because these two substrings have the subsequence `ABC` in common. (Note: the first row and column of the matrix are always filled with zeros.)
3636

37-
Here is the source code for `lcsLength()`; this lives in an extension on `String`:
37+
Here is the source code for `lcsLength(_:)`; this lives in an extension on `String`:
3838

3939
```swift
40-
func lcsLength(other: String) -> [[Int]] {
40+
func lcsLength(_ other: String) -> [[Int]] {
4141

42-
var matrix = [[Int]](count: self.characters.count+1,
43-
repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0))
42+
var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1)
4443

45-
for (i, selfChar) in self.characters.enumerate() {
46-
for (j, otherChar) in other.characters.enumerate() {
44+
for (i, selfChar) in self.characters.enumerated() {
45+
for (j, otherChar) in other.characters.enumerated() {
4746
if otherChar == selfChar {
4847
// Common char found, add 1 to highest lcs found so far.
4948
matrix[i+1][j+1] = matrix[i][j] + 1
@@ -96,7 +95,7 @@ Now we compare `C` with `C`. These are equal, and we increment the length to `3`
9695
| X | 0 | | | | | | |
9796
```
9897

99-
And so on... this is how `lcsLength()` fills in the entire matrix.
98+
And so on... this is how `lcsLength(_:)` fills in the entire matrix.
10099

101100
## Backtracking to find the actual subsequence
102101

@@ -125,7 +124,7 @@ One thing to notice is, as it's running backwards, the LCS is built in reverse o
125124
Here is the backtracking code:
126125

127126
```swift
128-
func backtrack(matrix: [[Int]]) -> String {
127+
func backtrack(_ matrix: [[Int]]) -> String {
129128
var i = self.characters.count
130129
var j = other.characters.count
131130

@@ -141,14 +140,14 @@ func backtrack(matrix: [[Int]]) -> String {
141140
// Indicates propagation without change: no new char was added to lcs.
142141
else if matrix[i][j] == matrix[i - 1][j] {
143142
i -= 1
144-
charInSequence = charInSequence.predecessor()
143+
charInSequence = self.index(before: charInSequence)
145144
}
146145
// Value on the left and above are different than current cell.
147146
// This means 1 was added to lcs length.
148147
else {
149148
i -= 1
150149
j -= 1
151-
charInSequence = charInSequence.predecessor()
150+
charInSequence = self.index(before: charInSequence)
152151
lcs.append(self[charInSequence])
153152
}
154153
}
@@ -165,17 +164,17 @@ Due to backtracking, characters are added in reverse order, so at the end of the
165164

166165
## Putting it all together
167166

168-
To find the LCS between two strings, we first call `lcsLength()` and then `backtrack()`:
167+
To find the LCS between two strings, we first call `lcsLength(_:)` and then `backtrack(_:)`:
169168

170169
```swift
171170
extension String {
172-
public func longestCommonSubsequence(other: String) -> String {
171+
public func longestCommonSubsequence(_ other: String) -> String {
173172

174-
func lcsLength(other: String) -> [[Int]] {
173+
func lcsLength(_ other: String) -> [[Int]] {
175174
...
176175
}
177176

178-
func backtrack(matrix: [[Int]]) -> String {
177+
func backtrack(_ matrix: [[Int]]) -> String {
179178
...
180179
}
181180

Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj

+40-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
isa = PBXProject;
8383
attributes = {
8484
LastSwiftUpdateCheck = 0720;
85-
LastUpgradeCheck = 0720;
85+
LastUpgradeCheck = 0800;
8686
TargetAttributes = {
8787
4716C7A61C93750500F6C1C0 = {
8888
CreatedOnToolsVersion = 7.2.1;
@@ -132,12 +132,49 @@
132132
4716C7861C936DCB00F6C1C0 /* Debug */ = {
133133
isa = XCBuildConfiguration;
134134
buildSettings = {
135+
CLANG_WARN_BOOL_CONVERSION = YES;
136+
CLANG_WARN_CONSTANT_CONVERSION = YES;
137+
CLANG_WARN_EMPTY_BODY = YES;
138+
CLANG_WARN_ENUM_CONVERSION = YES;
139+
CLANG_WARN_INFINITE_RECURSION = YES;
140+
CLANG_WARN_INT_CONVERSION = YES;
141+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
142+
CLANG_WARN_UNREACHABLE_CODE = YES;
143+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
144+
ENABLE_STRICT_OBJC_MSGSEND = YES;
145+
ENABLE_TESTABILITY = YES;
146+
GCC_NO_COMMON_BLOCKS = YES;
147+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
148+
GCC_WARN_ABOUT_RETURN_TYPE = YES;
149+
GCC_WARN_UNDECLARED_SELECTOR = YES;
150+
GCC_WARN_UNINITIALIZED_AUTOS = YES;
151+
GCC_WARN_UNUSED_FUNCTION = YES;
152+
GCC_WARN_UNUSED_VARIABLE = YES;
153+
ONLY_ACTIVE_ARCH = YES;
135154
};
136155
name = Debug;
137156
};
138157
4716C7871C936DCB00F6C1C0 /* Release */ = {
139158
isa = XCBuildConfiguration;
140159
buildSettings = {
160+
CLANG_WARN_BOOL_CONVERSION = YES;
161+
CLANG_WARN_CONSTANT_CONVERSION = YES;
162+
CLANG_WARN_EMPTY_BODY = YES;
163+
CLANG_WARN_ENUM_CONVERSION = YES;
164+
CLANG_WARN_INFINITE_RECURSION = YES;
165+
CLANG_WARN_INT_CONVERSION = YES;
166+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
167+
CLANG_WARN_UNREACHABLE_CODE = YES;
168+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
169+
ENABLE_STRICT_OBJC_MSGSEND = YES;
170+
GCC_NO_COMMON_BLOCKS = YES;
171+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
172+
GCC_WARN_ABOUT_RETURN_TYPE = YES;
173+
GCC_WARN_UNDECLARED_SELECTOR = YES;
174+
GCC_WARN_UNINITIALIZED_AUTOS = YES;
175+
GCC_WARN_UNUSED_FUNCTION = YES;
176+
GCC_WARN_UNUSED_VARIABLE = YES;
177+
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
141178
};
142179
name = Release;
143180
};
@@ -187,6 +224,7 @@
187224
PRODUCT_NAME = "$(TARGET_NAME)";
188225
SDKROOT = macosx;
189226
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
227+
SWIFT_VERSION = 3.0;
190228
};
191229
name = Debug;
192230
};
@@ -228,6 +266,7 @@
228266
PRODUCT_BUNDLE_IDENTIFIER = me.pedrovereza.Tests;
229267
PRODUCT_NAME = "$(TARGET_NAME)";
230268
SDKROOT = macosx;
269+
SWIFT_VERSION = 3.0;
231270
};
232271
name = Release;
233272
};

Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "0720"
3+
LastUpgradeVersion = "0800"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

0 commit comments

Comments
 (0)