Skip to content

Commit

Permalink
Merge branch 'master' into rbtree-improve
Browse files Browse the repository at this point in the history
  • Loading branch information
kelvinlauKL authored Aug 29, 2020
2 parents b36304c + 617187b commit 467ac6b
Show file tree
Hide file tree
Showing 421 changed files with 9,667 additions and 6,698 deletions.
4 changes: 2 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Want to help out with the Swift Algorithm Club? Great! While we don't have stric

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.

> 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.
> 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.
**API Design Guidelines**

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

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

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.
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.

### New Contributions

Expand Down
49 changes: 0 additions & 49 deletions .travis.yml

This file was deleted.

4 changes: 4 additions & 0 deletions 3Sum and 4Sum/3Sum.playground/Contents.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// last checked with Xcode 10.1
#if swift(>=4.2)
print("Hello, Swift 4.2!")
#endif

extension Collection where Element: Equatable {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
5 changes: 5 additions & 0 deletions 3Sum and 4Sum/4Sum.playground/Contents.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// last checked with Xcode 10.1
#if swift(>=4.2)
print("Hello, Swift 4.2!")
#endif

extension Collection where Element: Equatable {

/// In a sorted collection, replaces the given index with a successor mapping to a unique element.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
153 changes: 153 additions & 0 deletions A-Star/AStar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Written by Alejandro Isaza.

import Foundation

public protocol Graph {
associatedtype Vertex: Hashable
associatedtype Edge: WeightedEdge where Edge.Vertex == Vertex

/// Lists all edges going out from a vertex.
func edgesOutgoing(from vertex: Vertex) -> [Edge]
}

public protocol WeightedEdge {
associatedtype Vertex

/// The edge's cost.
var cost: Double { get }

/// The target vertex.
var target: Vertex { get }
}

public final class AStar<G: Graph> {
/// The graph to search on.
public let graph: G

/// The heuristic cost function that estimates the cost between two vertices.
///
/// - Note: The heuristic function needs to always return a value that is lower-than or equal to the actual
/// cost for the resulting path of the A* search to be optimal.
public let heuristic: (G.Vertex, G.Vertex) -> Double

/// Open list of nodes to expand.
private var open: HashedHeap<Node<G.Vertex>>

/// Closed list of vertices already expanded.
private var closed = Set<G.Vertex>()

/// Actual vertex cost for vertices we already encountered (refered to as `g` on the literature).
private var costs = Dictionary<G.Vertex, Double>()

/// Store the previous node for each expanded node to recreate the path.
private var parents = Dictionary<G.Vertex, G.Vertex>()

/// Initializes `AStar` with a graph and a heuristic cost function.
public init(graph: G, heuristic: @escaping (G.Vertex, G.Vertex) -> Double) {
self.graph = graph
self.heuristic = heuristic
open = HashedHeap(sort: <)
}

/// Finds an optimal path between `source` and `target`.
///
/// - Precondition: both `source` and `target` belong to `graph`.
public func path(start: G.Vertex, target: G.Vertex) -> [G.Vertex] {
open.insert(Node<G.Vertex>(vertex: start, cost: 0, estimate: heuristic(start, target)))
while !open.isEmpty {
guard let node = open.remove() else {
break
}
costs[node.vertex] = node.cost

if (node.vertex == target) {
let path = buildPath(start: start, target: target)
cleanup()
return path
}

if !closed.contains(node.vertex) {
expand(node: node, target: target)
closed.insert(node.vertex)
}
}

// No path found
return []
}

private func expand(node: Node<G.Vertex>, target: G.Vertex) {
let edges = graph.edgesOutgoing(from: node.vertex)
for edge in edges {
let g = cost(node.vertex) + edge.cost
if g < cost(edge.target) {
open.insert(Node<G.Vertex>(vertex: edge.target, cost: g, estimate: heuristic(edge.target, target)))
parents[edge.target] = node.vertex
}
}
}

private func cost(_ vertex: G.Edge.Vertex) -> Double {
if let c = costs[vertex] {
return c
}

let node = Node(vertex: vertex, cost: Double.greatestFiniteMagnitude, estimate: 0)
if let index = open.index(of: node) {
return open[index].cost
}

return Double.greatestFiniteMagnitude
}

private func buildPath(start: G.Vertex, target: G.Vertex) -> [G.Vertex] {
var path = Array<G.Vertex>()
path.append(target)

var current = target
while current != start {
guard let parent = parents[current] else {
return [] // no path found
}
current = parent
path.append(current)
}

return path.reversed()
}

private func cleanup() {
open.removeAll()
closed.removeAll()
parents.removeAll()
}
}

private struct Node<V: Hashable>: Hashable, Comparable {
/// The graph vertex.
var vertex: V

/// The actual cost between the start vertex and this vertex.
var cost: Double

/// Estimated (heuristic) cost betweent this vertex and the target vertex.
var estimate: Double

public init(vertex: V, cost: Double, estimate: Double) {
self.vertex = vertex
self.cost = cost
self.estimate = estimate
}

static func < (lhs: Node<V>, rhs: Node<V>) -> Bool {
return lhs.cost + lhs.estimate < rhs.cost + rhs.estimate
}

static func == (lhs: Node<V>, rhs: Node<V>) -> Bool {
return lhs.vertex == rhs.vertex
}

var hashValue: Int {
return vertex.hashValue
}
}
12 changes: 12 additions & 0 deletions A-Star/Images/graph.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "h = 3" ] }
{ rank = same; B [ label = "h = 2" ]; C [ label = "h = 2" ]; D [ label = "h = 2" ] }
{ rank = same; E [ label = "h = 1" ]; F [ label = "h = 1" ]; G [ label = "h = 1" ] }
{ H [ label = "h = 0", style = filled, color = green ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step1.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = deepskyblue1 ] }
{ 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 ] }
{ rank = same; E [ label = "g = \?\nh = 1" ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] }
{ H [ label = "g = \?\nh = 0" ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step2.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
{ 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 ] }
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] }
{ H [ label = "g = \?\nh = 0" ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step3.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
{ 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 ] }
{ rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] }
{ H [ label = "g = \?\nh = 0" ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step4.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
{ 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 ] }
{ 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 ] }
{ H [ label = "g = \?\nh = 0" ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step5.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
{ 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 ] }
{ 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 ] }
{ H [ label = "g = \?\nh = 0" ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step6.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
{ 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 ] }
{ 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 ] }
{ H [ label = "g = 3\nh = 0", style = filled, color = lightgrey ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions A-Star/Images/step7.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
{ A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] }
{ 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 ] }
{ 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 ] }
{ H [ label = "g = 3\nh = 0", style = filled, color = deepskyblue1 ] }
A -> { B C D }
B -> E
E -> F
D -> G
G -> H
}
Binary file added A-Star/Images/step7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 467ac6b

Please sign in to comment.