Skip to content

Commit 467ac6b

Browse files
authored
Merge branch 'master' into rbtree-improve
2 parents b36304c + 617187b commit 467ac6b

File tree

421 files changed

+9667
-6698
lines changed

Some content is hidden

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

421 files changed

+9667
-6698
lines changed

.github/CONTRIBUTING.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Want to help out with the Swift Algorithm Club? Great! While we don't have stric
66

77
Our repo is all about learning. The `README` file is the cake, and the sample code is the cherry on top. A good contribution has succinct explanations supported by diagrams. Code is best introduced in chunks, weaved into the explanations where relevant.
88

9-
> When choosing between brievity and performance, err to the side of brievity as long as the time complexity of the particular implementation is the same. You can make a note afterwards suggesting a more performant way of doing things.
9+
> When choosing between brevity and performance, err to the side of brevity as long as the time complexity of the particular implementation is the same. You can make a note afterwards suggesting a more performant way of doing things.
1010
1111
**API Design Guidelines**
1212

@@ -22,7 +22,7 @@ We follow the following Swift [style guide](https://github.com/raywenderlich/swi
2222

2323
Unit tests. Fixes for typos. No contribution is too small. :-)
2424

25-
The repository has over 100 different data structures and algorithms. We're always interested in improvements to existing implementations and better explanations. Suggestions for making the code more Swift-like or to make it fit better with the standard library is most welcomed.
25+
The repository has over 100 different data structures and algorithms. We're always interested in improvements to existing implementations and better explanations. Suggestions for making the code more Swift-like or to make it fit better with the standard library are most welcome.
2626

2727
### New Contributions
2828

.travis.yml

-49
This file was deleted.

3Sum and 4Sum/3Sum.playground/Contents.swift

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// last checked with Xcode 10.1
2+
#if swift(>=4.2)
3+
print("Hello, Swift 4.2!")
4+
#endif
15

26
extension Collection where Element: Equatable {
37

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

3Sum and 4Sum/4Sum.playground/Contents.swift

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// last checked with Xcode 10.1
2+
#if swift(>=4.2)
3+
print("Hello, Swift 4.2!")
4+
#endif
5+
16
extension Collection where Element: Equatable {
27

38
/// In a sorted collection, replaces the given index with a successor mapping to a unique element.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

A-Star/AStar.swift

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Written by Alejandro Isaza.
2+
3+
import Foundation
4+
5+
public protocol Graph {
6+
associatedtype Vertex: Hashable
7+
associatedtype Edge: WeightedEdge where Edge.Vertex == Vertex
8+
9+
/// Lists all edges going out from a vertex.
10+
func edgesOutgoing(from vertex: Vertex) -> [Edge]
11+
}
12+
13+
public protocol WeightedEdge {
14+
associatedtype Vertex
15+
16+
/// The edge's cost.
17+
var cost: Double { get }
18+
19+
/// The target vertex.
20+
var target: Vertex { get }
21+
}
22+
23+
public final class AStar<G: Graph> {
24+
/// The graph to search on.
25+
public let graph: G
26+
27+
/// The heuristic cost function that estimates the cost between two vertices.
28+
///
29+
/// - Note: The heuristic function needs to always return a value that is lower-than or equal to the actual
30+
/// cost for the resulting path of the A* search to be optimal.
31+
public let heuristic: (G.Vertex, G.Vertex) -> Double
32+
33+
/// Open list of nodes to expand.
34+
private var open: HashedHeap<Node<G.Vertex>>
35+
36+
/// Closed list of vertices already expanded.
37+
private var closed = Set<G.Vertex>()
38+
39+
/// Actual vertex cost for vertices we already encountered (refered to as `g` on the literature).
40+
private var costs = Dictionary<G.Vertex, Double>()
41+
42+
/// Store the previous node for each expanded node to recreate the path.
43+
private var parents = Dictionary<G.Vertex, G.Vertex>()
44+
45+
/// Initializes `AStar` with a graph and a heuristic cost function.
46+
public init(graph: G, heuristic: @escaping (G.Vertex, G.Vertex) -> Double) {
47+
self.graph = graph
48+
self.heuristic = heuristic
49+
open = HashedHeap(sort: <)
50+
}
51+
52+
/// Finds an optimal path between `source` and `target`.
53+
///
54+
/// - Precondition: both `source` and `target` belong to `graph`.
55+
public func path(start: G.Vertex, target: G.Vertex) -> [G.Vertex] {
56+
open.insert(Node<G.Vertex>(vertex: start, cost: 0, estimate: heuristic(start, target)))
57+
while !open.isEmpty {
58+
guard let node = open.remove() else {
59+
break
60+
}
61+
costs[node.vertex] = node.cost
62+
63+
if (node.vertex == target) {
64+
let path = buildPath(start: start, target: target)
65+
cleanup()
66+
return path
67+
}
68+
69+
if !closed.contains(node.vertex) {
70+
expand(node: node, target: target)
71+
closed.insert(node.vertex)
72+
}
73+
}
74+
75+
// No path found
76+
return []
77+
}
78+
79+
private func expand(node: Node<G.Vertex>, target: G.Vertex) {
80+
let edges = graph.edgesOutgoing(from: node.vertex)
81+
for edge in edges {
82+
let g = cost(node.vertex) + edge.cost
83+
if g < cost(edge.target) {
84+
open.insert(Node<G.Vertex>(vertex: edge.target, cost: g, estimate: heuristic(edge.target, target)))
85+
parents[edge.target] = node.vertex
86+
}
87+
}
88+
}
89+
90+
private func cost(_ vertex: G.Edge.Vertex) -> Double {
91+
if let c = costs[vertex] {
92+
return c
93+
}
94+
95+
let node = Node(vertex: vertex, cost: Double.greatestFiniteMagnitude, estimate: 0)
96+
if let index = open.index(of: node) {
97+
return open[index].cost
98+
}
99+
100+
return Double.greatestFiniteMagnitude
101+
}
102+
103+
private func buildPath(start: G.Vertex, target: G.Vertex) -> [G.Vertex] {
104+
var path = Array<G.Vertex>()
105+
path.append(target)
106+
107+
var current = target
108+
while current != start {
109+
guard let parent = parents[current] else {
110+
return [] // no path found
111+
}
112+
current = parent
113+
path.append(current)
114+
}
115+
116+
return path.reversed()
117+
}
118+
119+
private func cleanup() {
120+
open.removeAll()
121+
closed.removeAll()
122+
parents.removeAll()
123+
}
124+
}
125+
126+
private struct Node<V: Hashable>: Hashable, Comparable {
127+
/// The graph vertex.
128+
var vertex: V
129+
130+
/// The actual cost between the start vertex and this vertex.
131+
var cost: Double
132+
133+
/// Estimated (heuristic) cost betweent this vertex and the target vertex.
134+
var estimate: Double
135+
136+
public init(vertex: V, cost: Double, estimate: Double) {
137+
self.vertex = vertex
138+
self.cost = cost
139+
self.estimate = estimate
140+
}
141+
142+
static func < (lhs: Node<V>, rhs: Node<V>) -> Bool {
143+
return lhs.cost + lhs.estimate < rhs.cost + rhs.estimate
144+
}
145+
146+
static func == (lhs: Node<V>, rhs: Node<V>) -> Bool {
147+
return lhs.vertex == rhs.vertex
148+
}
149+
150+
var hashValue: Int {
151+
return vertex.hashValue
152+
}
153+
}

A-Star/Images/graph.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "h = 3" ] }
4+
{ rank = same; B [ label = "h = 2" ]; C [ label = "h = 2" ]; D [ label = "h = 2" ] }
5+
{ rank = same; E [ label = "h = 1" ]; F [ label = "h = 1" ]; G [ label = "h = 1" ] }
6+
{ H [ label = "h = 0", style = filled, color = green ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/graph.png

20.4 KB
Loading

A-Star/Images/step1.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = deepskyblue1 ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; C [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] }
5+
{ rank = same; E [ label = "g = \?\nh = 1" ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] }
6+
{ H [ label = "g = \?\nh = 0" ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step1.png

28.1 KB
Loading

A-Star/Images/step2.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ]; C [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] }
5+
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] }
6+
{ H [ label = "g = \?\nh = 0" ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step2.png

28.4 KB
Loading

A-Star/Images/step3.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] }
5+
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] }
6+
{ H [ label = "g = \?\nh = 0" ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step3.png

29.5 KB
Loading

A-Star/Images/step4.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ] }
5+
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = 2\nh = 1", style = filled, color = lightgrey ] }
6+
{ H [ label = "g = \?\nh = 0" ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step4.png

29.4 KB
Loading

A-Star/Images/step5.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] }
5+
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = deepskyblue1 ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = lightgrey ] }
6+
{ H [ label = "g = \?\nh = 0" ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step5.png

29.1 KB
Loading

A-Star/Images/step6.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] }
5+
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightblue ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = deepskyblue1 ] }
6+
{ H [ label = "g = 3\nh = 0", style = filled, color = lightgrey ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step6.png

28.9 KB
Loading

A-Star/Images/step7.dot

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
digraph G {
2+
rankdir=LR;
3+
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
4+
{ rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] }
5+
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightblue ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = lightblue ] }
6+
{ H [ label = "g = 3\nh = 0", style = filled, color = deepskyblue1 ] }
7+
A -> { B C D }
8+
B -> E
9+
E -> F
10+
D -> G
11+
G -> H
12+
}

A-Star/Images/step7.png

29.3 KB
Loading

0 commit comments

Comments
 (0)