Skip to content

Commit 3960cf5

Browse files
authored
Merge pull request kodecocodes#3 from raywenderlich/master
update fork
2 parents 1945830 + e340318 commit 3960cf5

File tree

43 files changed

+1426
-1926
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1426
-1926
lines changed

.travis.yml

+2-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
@@ -39,3 +39,4 @@ script:
3939
# - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests
4040
- xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests
4141
# - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests
42+
- xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests

Boyer-Moore/BoyerMoore.playground/Contents.swift

+9-11
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ extension String {
77
assert(patternLength <= self.characters.count)
88

99
var skipTable = [Character: Int]()
10-
for (i, c) in pattern.characters.enumerate() {
10+
for (i, c) in pattern.characters.enumerated() {
1111
skipTable[c] = patternLength - i - 1
1212
}
1313

14-
let p = pattern.endIndex.predecessor()
14+
let p = pattern.index(before: pattern.endIndex)
1515
let lastChar = pattern[p]
16-
var i = self.startIndex.advancedBy(patternLength - 1)
16+
var i = self.index(startIndex, offsetBy: patternLength - 1)
1717

1818
func backwards() -> String.Index? {
1919
var q = p
2020
var j = i
2121
while q > pattern.startIndex {
22-
j = j.predecessor()
23-
q = q.predecessor()
22+
j = index(before: j)
23+
q = index(before: q)
2424
if self[j] != pattern[q] { return nil }
2525
}
2626
return j
@@ -30,21 +30,19 @@ extension String {
3030
let c = self[i]
3131
if c == lastChar {
3232
if let k = backwards() { return k }
33-
i = i.successor()
33+
i = index(after: i)
3434
} else {
35-
i = i.advancedBy(skipTable[c] ?? patternLength)
35+
i = index(i, offsetBy: skipTable[c] ?? patternLength)
3636
}
3737
}
3838
return nil
3939
}
4040
}
4141

42-
43-
4442
// A few simple tests
4543

4644
let s = "Hello, World"
47-
s.indexOf("World") // 7
45+
s.indexOf(pattern: "World") // 7
4846

4947
let animals = "🐶🐔🐷🐮🐱"
50-
animals.indexOf("🐮") // 6
48+
animals.indexOf(pattern: "🐮") // 6

Boyer-Moore/BoyerMoore.playground/timeline.xctimeline

+15
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,20 @@
22
<Timeline
33
version = "3.0">
44
<TimelineItems>
5+
<LoggerValueHistoryTimelineItem
6+
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=345&amp;EndingColumnNumber=37&amp;EndingLineNumber=9&amp;StartingColumnNumber=9&amp;StartingLineNumber=9&amp;Timestamp=497585369.829471"
7+
selectedRepresentationIndex = "0"
8+
shouldTrackSuperviewWidth = "NO">
9+
</LoggerValueHistoryTimelineItem>
10+
<LoggerValueHistoryTimelineItem
11+
documentLocation = "#CharacterRangeLen=0&amp;CharacterRangeLoc=345&amp;EndingColumnNumber=26&amp;EndingLineNumber=9&amp;StartingColumnNumber=9&amp;StartingLineNumber=9&amp;Timestamp=497585369.82964"
12+
selectedRepresentationIndex = "0"
13+
shouldTrackSuperviewWidth = "NO">
14+
</LoggerValueHistoryTimelineItem>
15+
<LoggerValueHistoryTimelineItem
16+
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=345&amp;EndingColumnNumber=25&amp;EndingLineNumber=9&amp;StartingColumnNumber=9&amp;StartingLineNumber=9&amp;Timestamp=497585369.82978"
17+
selectedRepresentationIndex = "0"
18+
shouldTrackSuperviewWidth = "NO">
19+
</LoggerValueHistoryTimelineItem>
520
</TimelineItems>
621
</Timeline>

Boyer-Moore/README.markdown

+61-52
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ For example:
99
```swift
1010
// Input:
1111
let s = "Hello, World"
12-
s.indexOf("World")
12+
s.indexOf(pattern: "World")
1313

1414
// Output:
1515
<String.Index?> 7
1616

1717
// Input:
1818
let animals = "🐶🐔🐷🐮🐱"
19-
animals.indexOf("🐮")
19+
animals.indexOf(pattern: "🐮")
2020

2121
// Output:
2222
<String.Index?> 6
@@ -32,7 +32,7 @@ Here's how you could write it in Swift:
3232

3333
```swift
3434
extension String {
35-
func indexOf(pattern: String) -> String.Index? {
35+
func indexOf(pattern: String) -> String.Index? {
3636
// Cache the length of the search pattern because we're going to
3737
// use it a few times and it's expensive to calculate.
3838
let patternLength = pattern.characters.count
@@ -42,57 +42,58 @@ extension String {
4242
// Make the skip table. This table determines how far we skip ahead
4343
// when a character from the pattern is found.
4444
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
4747
}
4848

4949
// This points at the last character in the pattern.
50-
let p = pattern.endIndex.predecessor()
50+
let p = index(before: pattern.endIndex)
5151
let lastChar = pattern[p]
5252

5353
// The pattern is scanned right-to-left, so skip ahead in the string by
5454
// the length of the pattern. (Minus 1 because startIndex already points
5555
// 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)
5757

58-
// This is a helper function that steps backwards through both strings
58+
// This is a helper function that steps backwards through both strings
5959
// until we find a character that doesn’t match, or until we’ve reached
6060
// the beginning of the pattern.
6161
func backwards() -> String.Index? {
62-
var q = p
63-
var j = i
64-
while q > pattern.startIndex {
65-
j = j.predecessor()
66-
q = q.predecessor()
67-
if self[j] != pattern[q] { return nil }
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+
if self[j] != pattern[q] { return nil }
68+
}
69+
return j
7070
}
7171

7272
// The main loop. Keep going until the end of the string is reached.
7373
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-
if let 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+
if let 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+
}
9292
}
9393
return nil
94-
}
94+
}
9595
}
96+
9697
```
9798

9899
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:
149150

150151
```swift
151152
extension String {
152-
public func indexOf(pattern: String) -> String.Index? {
153+
func indexOf(pattern: String) -> String.Index? {
153154
let patternLength = pattern.characters.count
154155
assert(patternLength > 0)
155156
assert(patternLength <= self.characters.count)
156157

157158
var skipTable = [Character: Int]()
158-
for (i, c) in pattern.characters.dropLast().enumerate() {
159-
skipTable[c] = patternLength - i - 1
159+
for (i, c) in pattern.characters.enumerated() {
160+
skipTable[c] = patternLength - i - 1
160161
}
161162

162-
var index = self.startIndex.advancedBy(patternLength - 1)
163-
164-
while index < self.endIndex {
165-
var i = index
166-
var p = pattern.endIndex.predecessor()
167-
168-
while self[i] == pattern[p] {
169-
if p == pattern.startIndex { return i }
170-
i = i.predecessor()
171-
p = p.predecessor()
172-
}
163+
let p = pattern.index(before: pattern.endIndex)
164+
let lastChar = pattern[p]
165+
var i = self.index(startIndex, offsetBy: patternLength - 1)
173166

174-
let advance = skipTable[self[index]] ?? patternLength
175-
index = index.advancedBy(advance)
167+
func backwards() -> String.Index? {
168+
var q = p
169+
var j = i
170+
while q > pattern.startIndex {
171+
j = index(before: j)
172+
q = index(before: q)
173+
if self[j] != pattern[q] { return nil }
174+
}
175+
return j
176176
}
177177

178+
while i < self.endIndex {
179+
let c = self[i]
180+
if c == lastChar {
181+
if let k = backwards() { return k }
182+
i = index(after: i)
183+
} else {
184+
i = index(i, offsetBy: skipTable[c] ?? patternLength)
185+
}
186+
}
178187
return nil
179-
}
188+
}
180189
}
181190
```
182191

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
import UIKit
3+
4+
func haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double {
5+
6+
let haversin = { (angle: Double) -> Double in
7+
return (1 - cos(angle))/2
8+
}
9+
10+
let ahaversin = { (angle: Double) -> Double in
11+
return 2*asin(sqrt(angle))
12+
}
13+
14+
// Converts from degrees to radians
15+
let dToR = { (angle: Double) -> Double in
16+
return (angle / 360) * 2 * M_PI
17+
}
18+
19+
let lat1 = dToR(la1)
20+
let lon1 = dToR(lo1)
21+
let lat2 = dToR(la2)
22+
let lon2 = dToR(lo2)
23+
24+
return radius * ahaversin(haversin(lat2 - lat1) + cos(lat1) * cos(lat2) * haversin(lon2 - lon1))
25+
}
26+
27+
let amsterdam = (52.3702, 4.8952)
28+
let newYork = (40.7128, -74.0059)
29+
30+
// Google says it's 5857 km so our result is only off by 2km which could be due to all kinds of things, not sure how google calculates the distance or which latitude and longitude google uses to calculate the distance.
31+
haversineDinstance(la1: amsterdam.0, lo1: amsterdam.1, la2: newYork.0, lo2: newYork.1)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>

HaversineDistance/HaversineDistance.playground/playground.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

HaversineDistance/README.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Haversine Distance
2+
3+
Calculates the distance on a sphere between two points given in latitude and longitude using the haversine formula.
4+
5+
The haversine formula can be found on [Wikipedia](https://en.wikipedia.org/wiki/Haversine_formula)
6+
7+
The Haversine Distance is implemented as a function as a class would be kind of overkill.
8+
9+
`haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double`
10+
11+
- `la1` is the latitude of point 1 in degrees.
12+
- `lo1` is the longitude of point 1 in degrees.
13+
- `la2` is the latitude of point 2 in degrees.
14+
- `lo2` is the longitude of point 2 in degrees.
15+
- `radius` is the radius of the sphere considered in meters, which defaults to the mean radius of the earth (from [WolframAlpha](http://www.wolframalpha.com/input/?i=earth+radius)).
16+
17+
The function contains 3 closures in order to make the code more readable and comparable to the Haversine formula given by the Wikipedia page mentioned above.
18+
19+
1. `haversine` implements the haversine, a trigonometric function.
20+
2. `ahaversine` the inverse function of the haversine.
21+
3. `dToR` a closure converting degrees to radians.
22+
23+
The result of `haversineDistance` is returned in meters.
24+
25+
*Written for Swift Algorithm Club by Jaap Wijnen.*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//: Playground - noun: a place where people can play
2+
3+
import Foundation
4+
5+
precedencegroup ExponentiativePrecedence {
6+
higherThan: MultiplicationPrecedence
7+
lowerThan: BitwiseShiftPrecedence
8+
associativity: left
9+
}
10+
11+
infix operator ^^: ExponentiativePrecedence
12+
func ^^ (radix: Int, power: Int) -> Int {
13+
return Int(pow(Double(radix), Double(power)))
14+
}
15+
16+
// Long Multiplication - O(n^2)
17+
func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int {
18+
let num1Array = String(num1).characters.reversed().map{ Int(String($0))! }
19+
let num2Array = String(num2).characters.reversed().map{ Int(String($0))! }
20+
21+
var product = Array(repeating: 0, count: num1Array.count + num2Array.count)
22+
23+
for i in num1Array.indices {
24+
var carry = 0
25+
for j in num2Array.indices {
26+
product[i + j] += carry + num1Array[i] * num2Array[j]
27+
carry = product[i + j] / base
28+
product[i + j] %= base
29+
}
30+
product[i + num2Array.count] += carry
31+
}
32+
33+
return Int(product.reversed().map{ String($0) }.reduce("", +))!
34+
}
35+
36+
// Karatsuba Multiplication - O(n^log2(3))
37+
func karatsuba(_ num1: Int, by num2: Int) -> Int {
38+
let num1Array = String(num1).characters
39+
let num2Array = String(num2).characters
40+
41+
guard num1Array.count > 1 && num2Array.count > 1 else {
42+
return multiply(num1, by: num2)
43+
}
44+
45+
let n = max(num1Array.count, num2Array.count)
46+
let nBy2 = n / 2
47+
48+
let a = num1 / 10^^nBy2
49+
let b = num1 % 10^^nBy2
50+
let c = num2 / 10^^nBy2
51+
let d = num2 % 10^^nBy2
52+
53+
let ac = karatsuba(a, by: c)
54+
let bd = karatsuba(b, by: d)
55+
let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd
56+
57+
let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd
58+
59+
return product
60+
}

0 commit comments

Comments
 (0)